JavaEE——文件内容的读写
JavaEE传送门 |
JavaEE
JavaEE——认识文件
JavaEE——File类
目录
- 文件内容的读写 —— 数据流
- 字节流
- InputStream
- OutputStream
- 字符流
- Reader
- Writer
- Scanner
- PrintWriter
文件内容的读写 —— 数据流
把读写文件的操作, 比喻成 "水流"
. (水的特点, 流动起来, 绵延不断)
比如: 我们想接 100ml 的水, 有好几种接法
- 一次接 1ml, 分 100 次接完
- 一次接 10ml, 分 10 次接完
- 一次接 50ml, 分 2 次接完
- …
我们读写文件也是一样, 我们想写 100 字节的数据到文件中, 我们可以
- 一次写 1 字节, 分 100 次写
- 一次写 10 字节, 分 10 次写
- 一次写 50 字节, 分 2 次写
- …
Java
标准库, 就在 " 流" 的概念上, 提供了一组类, 完成读写文件的操作. 分为
字节流 (以字节为基本单位), 适用于二进制文件
字符流 (以字符为基本单位), 适用于文本文件
字节流
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()
方法, 用来读数据, 把数据从硬盘中读到内存中
FileInputStream 构造方法
签名 | 说明 |
---|---|
FileInputStream(File file) | 利用 File 构造文件输入流 |
FileInputStream(String name) | 利用文件路径构造文件输入流 |
示例
- 打开文件
//相当于打开文件
InputStream inputStream = new FileInputStream("./heihei.txt");
# 注意 #
打开了文件, 进行操作后, 一定要记得关闭文件 ! !
//关闭文件
inputStream.close();
- 读文件 read()
while(true) {int b = inputStream.read();// 返回 -1 表示读完了if (b == -1) {break;}System.out.println(b);
}
- 完整代码
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;public class Test {public static void main(String[] args) throws IOException {InputStream inputStream = new FileInputStream("./heihei.txt");while(true) {int b = inputStream.read();if (b == -1) {break;}System.out.println(b);}inputStream.close();}
}
我们打开看一下 heihei.txt, 然后看一下运行结果
# 注意事项 #
进行文件操作的时候, 一定要记得进行 close ! !
每个进程都对应着 PCB (可能是多个), PCB 里面有一个字段, 文件描述表
. (同一个进程里多个 PCB 公共使用同一份文件描述表的)
文件描述表相当于是一个数组/ 顺序表.
进程每次打开一个文件, 都会在这个表里, 创建一个项, 这个项就表示一个文件.
如果关闭一个文件, 就会把表里的对应项给释放掉. 如果不关闭, 意味着这个表项就在这里占着位置.
如果持续打开文件, 而且从来不关, 此时表项就会被耗尽, 导致后续再打开文件, 就会打开失败.
就会造成文件资源泄露
, 这是一个非常严重的问题 ! !
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() | 关闭字节流 |
示例
public class Test {public static void main(String[] args) throws IOException {//只要打开文件成功, 就会把文件原有内容清空//OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。OutputStream outputStream = new FileOutputStream("./heihei.txt");outputStream.write(97);//aoutputStream.write(98);outputStream.write(99);//一定记得关闭outputStream.close();}
}
运行结果展示
字符流
Reader
方法
示例
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;public class Test {public static void main(String[] args) throws IOException {Reader reader = new FileReader("./heihei.txt");while (true) {int ret = reader.read();if(ret == -1) {break;}System.out.println((char)ret);}reader.close();}
}
heihei.txt 与 运行结果展示
Writer
方法
示例
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;public class Test {public static void main(String[] args) throws IOException {Writer writer = new FileWriter("./heihei.txt");writer.write("hello world");writer.close();}
}
运行结果展示
Scanner
针对文本文件, 使用字符流的时候, 还可以使用
Scanner
来进行读取
示例
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;public class Test {public static void main(String[] args) throws IOException {InputStream inputStream = new FileInputStream("./heihei.txt");// 从inputStream读取Scanner scanner = new Scanner(inputStream);//hasNext遇到空白符结束while (scanner.hasNext()) {System.out.println(scanner.next());}inputStream.close();}
}
heihei.txt 与 运行结果展示
# 注意 #
InputStream 是字节流. Scanner
是在 InputStream 的基础上, 包装出来了个字符流.
PrintWriter
PrintWriter 类中提供了我们熟悉的 print/println/printf
方法
示例
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;public class Test {public static void main(String[] args) throws IOException {OutputStream outputStream = null;try {outputStream = new FileOutputStream("./heihei.txt");PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println();printWriter.printf("a = %d", 10);//刷新缓冲区printWriter.flush();} finally {//保证文件一定能关闭防止资源泄露outputStream.close();}}
运行结果展示
# 注意 #
一定不要忘记调用flush
缓冲区其实就是一个 “内存空间”.
文件是在硬盘上的, 写文件操作, 就是在写硬盘, 但是写硬盘是一个低效操作 ! !
缓冲区满了会自动把内存缓冲区的数据写到硬盘中.
若缓冲区未满, 我们就需要调用 flush
手动刷新.
除了try finally
保证 close 还可以使用 try with resources
.
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;public class Demo5 {public static void main(String[] args) throws IOException {//把要关闭的对象写在 try() 中, 当try结束, 就会自动调用到对应对象的 close 方法//且支持一个 () 放对各对象, 多个对象的创建之间使用; 分割try (OutputStream outputStream = new FileOutputStream("./heihei.txt")){PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println();printWriter.printf("a = %d", 10);//刷新缓冲区printWriter.flush();}}
}