一、核心概念:流式处理与阻塞IO
Java IO 流是用于处理数据传输的抽象。它将数据视为一个有序的序列,从源头流向目的地。
-
字节流:以**字节(byte)**为单位处理数据,适用于所有类型的文件,如图片、视频、二进制文件。
InputStream(输入流)、OutputStream(输出流)。
-
字符流:以**字符(char)**为单位处理数据,专门用于处理文本文件。
Reader(输入流)、Writer(输出流)。
同步阻塞:传统的 Java IO 流是同步阻塞的。当调用 read() 或 write() 方法时,线程会被阻塞,直到数据传输完成。
二、装饰器模式:IO流的性能与功能增强
Java IO 流的设计采用了装饰器模式。开发者可以通过包装(wrap)基础流,来增强其功能。
1. 缓冲流(BufferedStream)
- 原理:
BufferedInputStream和BufferedOutputStream在内部维护一个缓冲区。它会一次性从底层流中读取或写入一个较大的数据块(默认 8KB),从而减少底层 IO 操作的次数,显著提升性能。 - 应用:适用于任何需要读写大文件或网络数据的场景。
2. 转换流(InputStreamReader)
- 原理:
InputStreamReader是一个连接字节流和字符流的桥梁。它在读取字节流时,会根据指定的编码(如 UTF-8)将其解码为字符流。 - 应用:解决文本文件在不同编码下的乱码问题。
3. 数据流(DataStream)
- 原理:
DataInputStream和DataOutputStream提供了直接读写 Java 基本类型(如int、double)的能力,而无需手动进行类型转换。
三、资源管理:try-with-resources的自动化
在 Java 7 之后,try-with-resources 语法被引入,它能够自动关闭实现了 AutoCloseable 接口的资源。
- 原理:
try-with-resources在编译后,会生成一个finally块。在这个finally块中,编译器会自动调用资源的close()方法,从而避免了因忘记关闭流而导致的资源泄漏。
// 使用 try-with-resources 自动关闭流
try (FileInputStream fis = new FileInputStream("file.txt");
BufferedInputStream bis = new BufferedInputStream(fis)) {
// 读取文件...
} catch (IOException e) {
e.printStackTrace();
}
四、性能与选型指南
-
文件读写:
- 文本文件:优先使用字符流(
FileReader、FileWriter),并结合缓冲流(BufferedReader、BufferedWriter)。 - 二进制文件:优先使用字节流(
FileInputStream、FileOutputStream),并结合缓冲流。
- 文本文件:优先使用字符流(
-
网络通信:
- 字节流:
Socket的InputStream和OutputStream是字节流。 - 字符流:如果需要处理文本数据,可以通过转换流将其转换为字符流。
- 字节流:
-
性能瓶颈:
read()方法一次读取一个字节,效率低下。应使用read(byte[] buffer)或read(char[] buffer),一次读取一个缓冲区。- NIO(New I/O)和 AIO(Asynchronous I/O)提供了非阻塞和异步的 IO 方式,适用于高并发的网络编程。