文件介绍
文件本身有多重含义,狭义的文件,特指硬盘上的文件(以及保存文件的目录),广义的文件:计算机上的很多硬件设备,软件资源,在操作系统中,都会被视为是"文件"
文件除了有数据内容之外,还有一部分信息,例如文件名,文件类型,文件大小,这些信息可以称作文件的元信息
树型结构组织和目录
在一个电脑上,有很多文件,文件数量太多,所以要对文件进行系统管理,操作系统专门有一个模块-"文件系统",一般是通过"文件资源管理器"观察到文件系统管理的文件.
进行文件的组织,采用了层级结构进行组织,也就是树型结构(n叉树),一种专门用来存放管理信息的特殊文件,即文件夹或者目录.
文件夹/目录中保存的就是关于文件的元信息
文件路径
如何在文件系统中定位唯一一个文件呢?
从树型结构的角度来看,树中的每个结点都可以被一条从根开始,一直到达的结点的路径所描述,这种描述方式就称为文件的绝对路径
例:
C:\Intel\iGfx\Vulkan
除了可以从根开始进行路径的描述,我们可以从任意结点出发,进行路径的描述,这种描述方式就被称为相对路径
相对路径可以是以下几种形式:
- 相对于当前目录:使用文件名或目录名即可,不需要任何前缀。例如,如果当前目录是 "/home/user",要引用同一目录下的 "file.txt",可以使用相对路径 "file.txt"。
- 相对于上级目录:使用 "../" 表示上级目录。例如,要引用上级目录中的文件 "parentfile.txt",可以使用相对路径 "../parentfile.txt"。
- 相对于任意目录:使用若干个 "../" 组合表示相对于当前目录的某一级别的上级目录。例如,要引用当前目录的上一级目录的子目录 "subdir" 下的文件 "subfile.txt",可以使用相对路径 "../../subdir/subfile.txt"。
文件属性
即使是普通文件,根据其保存数据的不同,我们一般简单的划分为文本文件和二进制文件
-
文本文件: 文本文件是以文本形式存储数据的文件。它由字符组成,每个字符都使用特定的编码方式表示。常见的文本文件格式包括TXT、CSV等。文本文件可以使用文本编辑器打开,并且可以直接阅读和编辑其中的内容。文本文件中的数据通常是以行为单位进行组织,每行数据可以包含字母、数字、符号等。
-
二进制文件: 二进制文件是以二进制形式存储数据的文件。它不是以字符的形式存在,而是以字节的形式存储。二进制文件可以包含任意类型的数据,如图片、音频、视频、程序等。二进制文件的内容无法直接阅读或编辑,需要使用特定的程序或工具进行解析和处理。二进制文件通常是使用特定的格式进行编码和存储,如JPEG、MP3、EXE等。
区别:
- 存储方式:文本文件以字符形式存储,二进制文件以字节形式存储。
- 可读性:文本文件内容可以直接阅读和编辑,而二进制文件内容通常需要特定的工具进行解析和处理。
- 文件大小:由于文本文件只存储字符,而二进制文件可以存储任意类型的数据,所以相同数据量下,二进制文件通常比文本文件更小。
- 处理效率:由于文本文件内容可以直接读取和处理,所以在某些情况下,处理文本文件可能更加高效。
文件操作
Java操作文件,通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述.
1.文件系统操作
File类
属性
修饰符及类型 | 属性 | 说明 |
---|---|---|
static String | pathSeparator | 依赖于系统的路径分隔符,String类型表示 |
static char | pathSeparator | 依赖于系统的路径分隔符,char类型的表示 |
构造方法
方法 | 说明 |
---|---|
File(File parent,String child) | 根据父目录+孩子文件路径,创建一个新的File实例 |
File(String pathname) | 根据文件路径创建一个新的File实例,路径可以是绝对路径或者相对路径 |
File(String parent,String child) | 根据父目录+孩子文件路径,创建一个新的File实例,父目录用路径表示 |
方法
修饰符及返回值类型 | 方法签名 | 说明 |
---|---|---|
String | getParent() | 返回FIle对象的父目录文件路径 |
String | getName() | 返回File对象的纯文件名称 |
Strng | getPath() | 返回File对象的文件路径 |
String | gerAbsolutePath() | 返回File对象的绝对路径 |
String | getCanonicalPath() | 返回File对象的修饰过的绝对路径 |
boolean | exists() | 判断File对象描述的文件是否真实存在 |
boolean | isDirectory() | 判断File对象代表的文件是否是一个目录 |
boolean | isFile() | 判断File对象代表的文件是否是一个普通文件 |
boolean | createNewFile() | 根据File对象,自动创建一个空文件,成功创建后返回true |
boolean | delete() | 根据File对象,删除该文件,成功删除后返回true |
void | deleteOnExit() | 根据File对象,标注文件将被删除,删除动作回到JVM运行结束时才会进行 |
String[] | list() | 返回File对象代表的目录下的所有文件名 |
File[] | listFiles() | 返回File对象代表的目录下的所有文件,以File对象表示 |
boolean | mkdir() | 创建File对象代表的目录 |
boolean | mkdirs() | 创建File对象代表的目录,如果必要,会创建中间目录 |
boolean | renameTo(File dest) | 进行文件改名,也可以视为我们平时的剪切,粘贴操作 |
boolean | canRead() | 判断用户是否对文件有可读权限 |
boolean | canWrite() | 判断用户是否对文件有可写权限 |
示例
1.获取文件相关信息
public static void main(String[] args) throws IOException {File file = new File("./text.txt");System.out.println(file.getParent());System.out.println(file.getName());System.out.println(file.getPath());System.out.println(file.getAbsolutePath());System.out.println(file.getCanonicalPath());}/*** 输出* .* text.txt* .\text.txt* D:\LXY_Java\javaa\Thread\.\text.txt* D:\LXY_Java\javaa\Thread\text.txt*/
2.创建新文件:
public static void main(String[] args) throws IOException {File file = new File("./test.txt");boolean ok = file.createNewFile();System.out.println(ok);System.out.println(file.exists());System.out.println(file.isFile());System.out.println(file.isDirectory());}/*** false* true* true* false*/
3.删除文件:
public static void main(String[] args) {File file = new File("./test.txt");boolean ok = file.delete();System.out.println(ok);}//true
public static void main(String[] args) {File file = new File("./test.txt");file.deleteOnExit();System.out.println("执行删除完毕");Scanner scanner = new Scanner(System.in);scanner.next();}
4.创建目录:
public static void main(String[] args) {File f = new File("./abc/def/ghi");boolean ok = f.mkdirs();System.out.println(ok);}
5.重命名
public static void main(String[] args) {File srcFile = new File("./abc/def");File destDile = new File("./aaa");boolean ok = srcFile.renameTo(destDile);System.out.println(ok);}
2.文件内容操作
数据流
数据流(Data Streams)是在程序中进行数据输入和输出的一种方式。数据流主要用于处理基本数据类型和对象的序列化和反序列化操作。
在Java中,数据流主要包括了两种类型:字节流和字符流。
字节流(Byte Streams)用于处理二进制数据,以字节(byte)为单位进行读取和写入。常见的字节流类有InputStream和OutputStream。
字符流(Character Streams)用于处理文本数据,以字符(char)为单位进行读取和写入。常见的字符流类有Reader和Writer。
InputStream
修饰符及返回值类型 | 方法 | 说明 |
---|---|---|
int | read() | 读取一个字节的数据,返回-1代表已经读完了 |
int | read(byte[] b) | 最多读取b.length字节的数据到b中,返回实际读到的数量.-1代表已经读完了 |
int | read(byte[] b,int off,int len) | 最多读取 len-off 字节的数据到b中,放在从 off 开始,返回实际读到的数量,-1代表已经读完 |
void | close() | 关闭字节流 |
使用 InputStream 的步骤一般包括以下几步:
- 创建 InputStream 的子类对象,如 FileInputStream,用于打开要读取的文件。
- 调用 InputStream 对象的 read()、read(byte[] b)、read(byte[] b, int off, int len) 方法读取字节数据。
- 处理读取到的数据。
- 关闭 InputStream 对象,释放资源,使用 close() 方法。
FileInputStream
方法 | 说明 |
---|---|
FileInputStream(File file) | 利用File构造文件输入流 |
FileInputStream(String name) | 利用文件路径构造文件输入流 |
利用Scanner进行字符读取
构造方法 | 说明 |
---|---|
Scanner(InputStream is,String charset) | 使用charset字符集进行is的扫描读取 |
示例
读取文件两种方式
上述图中
- read():调用一次读一个字节
- read(byte[] b,int off,int len):一次读取 b 中 [off,off+len)范围的区间
- read(byte[] b):一次读取 b 中所有字节
public static void main(String[] args) {try(InputStream inputStream = new FileInputStream("./test.txt")){while(true){int b = inputStream.read();if(b==-1){//读取完毕break;}//表示字节更习惯用16进制表现System.out.printf("0x%x\n",b);}}catch (IOException e){e.printStackTrace();}}
public static void main(String[] args) {try(InputStream inputStream = new FileInputStream("./test.txt")){while(true){byte[] buffer = new byte[1024];//n返回值表示read实际读取到int n = inputStream.read(buffer);if(n==-1){break;}for (int i = 0; i < n; i++) {System.out.printf("0x%x\n",buffer[i]);}}} catch (IOException e) {throw new RuntimeException(e);}}
使用scanner
public static void main(String[] args) throws IOException {try (InputStream is = new FileInputStream("test.txt")) {try (Scanner scanner = new Scanner(is, "UTF-8")) {while (scanner.hasNext()) {String s = scanner.next();System.out.print(s);}}}}
OutputStream
方法
修饰符及返回值类型 | 方法 | 说明 |
---|---|---|
void | write(int b) | 写入要给字节的数据 |
void | write(byte[] b) | 将b这个字符数组中的数据全部写入 os 中 |
int | write(byte[] b, int off, int len) | 将 b 这个字符数组中从off开始的数据写入os中,一共写len个 |
void | close() | 关闭字节流 |
void | flush() | 刷新输出流的缓冲区,将缓冲区中的数据立即写入到输出目的地中,而不是等待缓冲区满或者流关闭 |
示例
public static void main(String[] args) {try(OutputStream outputStream = new FileOutputStream("./test.txt",true)){outputStream.write(0xe4);outputStream.write(0xbd);outputStream.write(0xa0);outputStream.write(0xe5);outputStream.write(0xa5);outputStream.write(0xbd);outputStream.flush();} catch (IOException e) {throw new RuntimeException(e);}}//hello
Reader和Writer
Reader和Writer与InputStream和OutputStream类似,区别就是Reader和Writer以字符(char)为单位进行读取和写入
public static void main(String[] args) {try(Reader reader = new FileReader("./test.txt")){char[] buffer = new char[1024];int n = reader.read(buffer);System.out.println(n);for (int i = 0; i < n; i++) {System.out.println(buffer[i]);}} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}
public static void main(String[] args) {try(Writer writer = new FileWriter("./test.txt",true)){writer.write("你好世界");} catch (IOException e) {throw new RuntimeException(e);}}