Java 流(Stream)分类、用途与性能分析
Java中的I/O流提供了丰富的类库来处理输入输出操作。
主要分为字节流和字符流两大类。
下面我将从分类、用途和性能三个方面进行详细说明。
一、流的分类
1. 按数据单位分类
字节流 (Byte Streams)
- 
基础类:
InputStream和OutputStream - 
文件操作:
FileInputStream,FileOutputStream - 
缓冲流:
BufferedInputStream,BufferedOutputStream - 
对象序列化:
ObjectInputStream,ObjectOutputStream - 
数据转换:
DataInputStream,DataOutputStream 
字符流 (Character Streams)
- 
基础类:
Reader和Writer - 
文件操作:
FileReader,FileWriter - 
缓冲流:
BufferedReader,BufferedWriter - 
转换流:
InputStreamReader,OutputStreamWriter 
2. 按功能分类
节点流 (Node Streams)
- 
直接与数据源连接的流
 - 
示例:
FileInputStream,FileReader 
处理流 (Processing Streams)
- 
对节点流或其他处理流进行包装
 - 
提供额外功能(缓冲、数据类型转换等)
 - 
示例:
BufferedInputStream,BufferedReader 
二、主要流类的用途
字节流用途
- 
FileInputStream/FileOutputStream
- 
用于读写二进制文件
 - 
适合图像、音频、视频等非文本文件
 
 - 
 - 
BufferedInputStream/BufferedOutputStream
- 
提供缓冲功能,减少I/O操作次数
 - 
提高读写性能
 
 - 
 - 
DataInputStream/DataOutputStream
- 
读写基本数据类型和字符串
 - 
保持数据的原始格式
 
 - 
 - 
ObjectInputStream/ObjectOutputStream
- 
用于对象的序列化和反序列化
 
 - 
 
字符流用途
- 
FileReader/FileWriter
- 
用于读写文本文件
 - 
自动处理字符编码
 
 - 
 - 
BufferedReader/BufferedWriter
- 
提供缓冲功能
 - 
BufferedReader特有的readLine()方法 
 - 
 - 
InputStreamReader/OutputStreamWriter
- 
字节流与字符流之间的桥梁
 - 
可以指定字符编码
 
 - 
 
三、性能比较与最佳实践
性能比较
- 
无缓冲 vs 缓冲流
- 
无缓冲流每次读写都直接操作底层资源,性能较差
 - 
缓冲流通过内存缓冲区减少I/O操作次数,性能显著提升
 - 
典型缓冲区大小:8KB (可调整)
 
 - 
 - 
字节流 vs 字符流
- 
处理文本时字符流性能更好(避免了字节-字符转换)
 - 
处理二进制数据必须使用字节流
 
 - 
 - 
大文件处理
- 
缓冲流对大型文件性能提升更明显
 - 
对于超大文件,考虑使用内存映射文件(MappedByteBuffer)
 
 - 
 
实践分析
- 
始终使用缓冲流
// 不好的做法FileInputStream fis = new FileInputStream(\"file.txt\");// 好的做法InputStream is = new BufferedInputStream(new FileInputStream(\"file.txt\")); - 
正确处理字符编码
// 指定UTF-8编码Reader reader = new InputStreamReader( new FileInputStream(\"file.txt\"), StandardCharsets.UTF_8); - 
使用try-with-resources确保资源释放
try (BufferedReader br = new BufferedReader(new FileReader(\"file.txt\"))) { String line; while ((line = br.readLine()) != null) { // 处理每一行 }} - 
根据场景选择合适的流
- 
文本处理:字符流
 - 
二进制数据:字节流
 - 
网络通信:缓冲流 + 适当设置缓冲区大小
 
 - 
 - 
大文件处理优化
- 
使用NIO的
FileChannel和MappedByteBuffer处理超大文件 - 
分块读取处理,避免内存溢出
 
 - 
 
性能测试
public class StreamPerformanceTest { public static void main(String[] args) throws IOException { String filePath = \"large_file.txt\"; // 测试无缓冲字节流 long start = System.currentTimeMillis(); try (InputStream is = new FileInputStream(filePath)) { while (is.read() != -1); } System.out.println(\"FileInputStream: \" + (System.currentTimeMillis() - start) + \"ms\"); // 测试缓冲字节流 start = System.currentTimeMillis(); try (InputStream is = new BufferedInputStream(new FileInputStream(filePath))) { while (is.read() != -1); } System.out.println(\"BufferedInputStream: \" + (System.currentTimeMillis() - start) + \"ms\"); // 测试缓冲字符流 start = System.currentTimeMillis(); try (Reader reader = new BufferedReader(new FileReader(filePath))) { while (reader.read() != -1); } System.out.println(\"BufferedReader: \" + (System.currentTimeMillis() - start) + \"ms\"); }}
总结
选择原则:根据数据类型(文本/二进制)选择字符流或字节流,优先使用缓冲流
性能关键:减少实际I/O操作次数是提高性能的关键
编码注意:处理文本时始终明确字符编码
资源管理:使用try-with-resources确保流正确关闭
高级场景:对于超大规模I/O,考虑NIO或内存映射文件
正确选择和使用Java I/O流可以显著影响应用程序的性能和可靠性。


