Java IO 分类详解(传输方向 + 操作对象)
Java IO 的分类体系可从 传输方向(输入/输出)和 操作对象(字节/字符)两个维度展开,结合 节点流与处理流 的层次结构,形成完整的 IO 操作框架。以下是详细解析:
一、按传输方向分类
1. 输入流(Input Stream)
- 作用:从数据源读取数据(如文件、网络、内存)。
- 核心接口:
- 字节输入流:
InputStream(抽象类)FileInputStream:读取文件。ByteArrayInputStream:从字节数组读取。DataInputStream:读取基本类型(readInt(),readUTF())。ObjectInputStream:反序列化对象。
- 字符输入流:
Reader(抽象类)FileReader:读取文本文件。InputStreamReader:将字节流转换为字符流。BufferedReader:缓冲字符流,支持readLine()。
- 字节输入流:
2. 输出流(Output Stream)
- 作用:向目标写入数据(如文件、网络、内存)。
- 核心接口:
- 字节输出流:
OutputStream(抽象类)FileOutputStream:写入文件。ByteArrayOutputStream:向字节数组写入。DataOutputStream:写入基本类型。ObjectOutputStream:序列化对象。
- 字符输出流:
Writer(抽象类)FileWriter:写入文本文件。OutputStreamWriter:将字符流转换为字节流。BufferedWriter:缓冲字符流,支持newLine()。
- 字节输出流:
二、按操作对象分类
1. 字节流(Byte Stream)
- 单位:以
byte(8位)为单位操作数据。 - 适用场景:
- 二进制文件(如图片、音频、视频)。
- 网络传输(TCP/UDP 协议基于字节流)。
- 跨平台数据交换(避免字符编码问题)。
- 核心类:
InputStream/OutputStream及其子类。
2. 字符流(Character Stream)
- 单位:以
char(16位Unicode字符)为单位操作数据。 - 适用场景:
- 文本文件(如
.txt,.csv,.json)。 - 字符串处理(自动处理字符编码转换)。
- 文本文件(如
- 核心类:
Reader/Writer及其子类。
- 编码处理:
- 显式指定字符集(如
StandardCharsets.UTF_8):new InputStreamReader(new FileInputStream("file.txt"), "UTF-8");
- 显式指定字符集(如
三、节点流 vs 处理流
1. 节点流(Node Stream)
- 定义:直接操作数据源或目标的流。
- 示例:
FileInputStream:直接读取文件。Socket.getInputStream():从网络套接字读取数据。
2. 处理流(Processing Stream)
- 定义:包装其他流,增强功能(如缓冲、转换、格式化)。
- 常见处理流:
- 缓冲流:
BufferedInputStream/BufferedOutputStream:减少直接IO次数。BufferedReader/BufferedWriter:支持按行读写。
- 转换流:
InputStreamReader/OutputStreamWriter:字节流与字符流互转。
- 数据流:
DataInputStream/DataOutputStream:读写基本类型。
- 对象流:
ObjectInputStream/ObjectOutputStream:序列化/反序列化对象。
- 缓冲流:
3. 组合模式示例
// 读取文件内容并逐行处理
try (BufferedReader br = new BufferedReader(
new InputStreamReader(
new FileInputStream("data.txt"),
StandardCharsets.UTF_8
))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
四、分类选择策略
| 场景 | 推荐流类型 | 原因 |
|---|---|---|
| 读取文本文件 | BufferedReader 包装 FileReader | 支持按行读取,自动处理换行符 |
| 写入二进制数据 | DataOutputStream 包装 FileOutputStream | 支持直接写入 int/double 等基本类型 |
| 网络传输(TCP) | BufferedInputStream/BufferedOutputStream | 缓冲减少网络IO次数 |
| 跨平台数据交换 | 字节流(如 DataInputStream) | 避免字符编码问题 |
| 对象持久化 | ObjectOutputStream 包装 FileOutputStream | 实现序列化 |
五、高级主题
1. NIO 通道与缓冲区
- 通道(Channel):双向数据传输(如
FileChannel)。 - 缓冲区(Buffer):数据容器(如
ByteBuffer)。 - 示例:
try (FileChannel channel = FileChannel.open(Paths.get("data.txt"), StandardOpenOption.READ)) { ByteBuffer buffer = ByteBuffer.allocate(1024); while (channel.read(buffer) > 0) { buffer.flip(); // 切换为读模式 while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } buffer.clear(); // 清空缓冲区 } }
2. 零拷贝(Zero-Copy)
- 场景:大文件传输。
- 实现:通过
FileChannel.transferTo()/transferFrom()避免数据在内核空间和用户空间拷贝。
3. 文件锁(FileLock)
- 作用:控制多进程/线程对文件的并发访问。
- 示例:
try (RandomAccessFile file = new RandomAccessFile("data.txt", "rw"); FileChannel channel = file.getChannel(); FileLock lock = channel.lock()) { // 独占锁 // 读写文件 }
六、最佳实践
-
明确字符编码:
- 避免依赖平台默认编码,始终显式指定(如
StandardCharsets.UTF_8)。
- 避免依赖平台默认编码,始终显式指定(如
-
优先使用缓冲流:
- 减少直接IO操作次数,提升性能。
-
资源自动管理:
- 使用 try-with-resources 确保流关闭:
try (InputStream in = new FileInputStream("file.txt"); OutputStream out = new FileOutputStream("copy.txt")) { // 复制逻辑 }
- 使用 try-with-resources 确保流关闭:
-
选择合适的流类型:
- 二进制数据用字节流,文本数据用字符流。
通过理解Java IO的分类体系,可以更精准地选择工具类,提升代码效率和可维护性。实际开发中需结合场景权衡传统IO与NIO的适用性。
2576

被折叠的 条评论
为什么被折叠?



