文件IO
文件操作的基本知识
- 文件除了有数据内容之外,还有一部分信息,例如文件名、文件类型、文件大小等并不作为文件的数据而存在,我们把这部分信息可以视为文件的元信息。而目录就保存就保存着这些原信息。
- 文件的组织是按照层级结构进行组织,也就是我们数据结构中学习过的树形结构。
- 文件路径
- 绝对路径:从磁盘开始一直到当前文件这么一条完整路径为绝对路径(F:/CPC/IO/test/hello.txt)
- 相对路径:相对路径则要看当前在哪个位置,比如以上面绝对路径为例,现在在test路径下,则hello.txt的相对路径则为./hello.txt。如果在IO目录下,相对路径为./test/hello.txt。
- 由于Windows的路径分隔符和代码的有区别,在Windows下是反斜杠(\),但是这会导致代码的转义字符问题,所以要么使用转义字符来解决,如上面绝对路径可以改为(F:\\CPC\\IO\\test\\hello.txt)。
- “.”表示当前路径,“…”表示父路径。
Java中的文件操作
🎈文件操作
Java本地库中提供了File类(import java.io.File;)
🔭File的常用构造方法:
构造方法 | 说明 |
---|---|
File(String pathname) | 文件路径,路径可以是绝对路径或者相对路径 |
File(File parent, String child) | File parent父目录的文件引用,String child孩子文件路径 |
File(String parent, String child) | 父目录路径,孩子文件路径 |
🎯 实例一:创建一个TXT文件,如果存在则删除,不存在则创建,并打印该文件的名字
注意,有 File 对象,并不代表真实存在该文件。
public static void main(String[] args) throws IOException {
File file = new File("F:/CPC/File/hello.txt");// 绝对路径
if(!file.exists()) { // 判断文件是否存在
file.createNewFile(); // 创建文件
}else {
file.delete(); // 删除文件
}
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());// 文件修饰过的路径
}
📢结果:以文件不存在为例
true
false
F:\CPC\File
hello.txt
F:\CPC\File\hello.txt
F:\CPC\File\hello.txt
F:\CPC\File\hello.txt
💡使用 相对路径:
File file = new File("./hello.txt");
📢结果:
true
false
.
hello.txt
.\hello.txt
F:\CPC\File\.\hello.txt
F:\CPC\File\hello.txt // getCanonicalPath()对绝对路径进行了优化,去除了文件名前的.\
🎯实例二:创建一个目录,在这个目录下再创建两个目录,然后在目录二下面创建两个文件,最后打印目录二下面的所有文件名和文件路径。
注意,有 File 对象,并不代表真实存在该文件。
public static void main(String[] args) throws IOException {
File dir1 = new File("F:/CPC/IO");// 设置目录一
if(!dir1.exists()){
dir1.mkdir();// 创建目录一
File dir2 = new File(dir1,"test/hello");// 设置目录二
dir2.mkdirs();// 创建目录二,因为创建多个目录所以mkdirs
File file1 = new File(dir1,"test/hello1.txt");// 设置文件一
File file2 = new File(dir1,"test/hello2.txt");// 设置文件二
file1.createNewFile();// 创建文件一
file2.createNewFile();// 创建文件二
File dir3 = new File("../IO/test");// 设置目录三
String[] list1 = dir3.list();// 获取目录三下面的所有文件名
System.out.println(Arrays.toString(list1));
File[] list2 = dir3.listFiles();// 获取目录三下面的所有文件路径
System.out.println(Arrays.toString(list2));
}
}
📢结果:
[hello, hello1.txt, hello2.txt]
[..\IO\test\hello, ..\IO\test\hello1.txt, ..\IO\test\hello2.txt]
✍✍以上的则常用File类的常用方法。
🎈文件内容操作
文件根据内容类型可分为文本文件(字符流)和二进制文件(字节流)。
Java对文本文件的内容IO操作,常用的有Reader和Writer;
Java对二进制文件的内容IO操作,常见的有InputStream和OutputStream。
📌注意:IO操作的方向理解,IO是对磁盘上的文件操作,从磁盘读到内存在到CPU是输入(磁盘->内存->CPU),从CPU读到内存在到磁盘是输出(CPU->内存->磁盘)。
二进制文件内容操作,InputStream和OutputStream。InputStream和OutputStream都是抽象类,所以要实例化子类对象,InputStream对应的子类是FileInputStream,OutputStream对应的子类是FileOutputStream。
🔭InputStream和OutputStream的常用两种构造:
构造方法 | |
---|---|
FileInputStream(File file) | 利用 File 构造文件输入流 |
FileInputStream(String name) | 利用文件路径构造文件输入流 |
FileOutputStream(File file) | 利用 File 构造文件输出流 |
FileOutputStream(String name) | 利用文件路径构造文件输出流 |
🔭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() | 关闭字节流 |
💡read方法读的是字节,为什么返回值是-1?
读字节那么都是无符号,则是0~255,用-1标识文件读完了,所以用int。
🔭OutputStream的常用方法:
修饰符及返回值类型 | 方法 | 说明 |
---|---|---|
void | write(int b) | 写入要给字节的数据 |
void | write(byte[] b) | 将 b 这个字符数组中的数据全部写入文件中 |
int | write(byte[] b, int off, int len) | 将 b 这个字符数组中从 off 开始的数据写入文件中,一共写 len 个 |
void | flush() | 重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为 了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写 入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置, 调用 flush(刷新)操作,将数据刷到设备中。 |
void | close() | 关闭字节流 |
🎯实例:在文件操作创建的hello1.txt中直接设置一个单词,在hello2.txt中输出单词中包含多少个大写字母‘A’。
public static void main(String[] args) {
try (InputStream inputStream = new FileInputStream("F:/CPC/IO/test/hello1.txt")) {
int count = 0;
while (true) {
int flag = inputStream.read();
if (flag == -1) {
break;
} else if (flag == 65) {
count++;
}
}
try (OutputStream outputStream = new FileOutputStream("F:/CPC/IO/test/hello2.txt")) {
outputStream.write(count + '0');
}
} catch (IOException e) {
e.printStackTrace();
}
}
📢结果:
hello1.txt:设置BANANA
hello2.txt中结果:
3
📌注意上述try catch使用的是 try with resources的写法,因为InputStream和OutputStream都实现了Closeable接口所以可以帮助关闭文件,防止资源泄露。