> 技术文档 > Java 流(Stream)分类、用途与性能分析

Java 流(Stream)分类、用途与性能分析


Java中的I/O流提供了丰富的类库来处理输入输出操作。

主要分为字节流和字符流两大类。

下面我将从分类、用途和性能三个方面进行详细说明。


一、流的分类

1. 按数据单位分类

字节流 (Byte Streams)
  • 基础类:InputStream 和 OutputStream

  • 文件操作:FileInputStreamFileOutputStream

  • 缓冲流:BufferedInputStreamBufferedOutputStream

  • 对象序列化:ObjectInputStreamObjectOutputStream

  • 数据转换:DataInputStreamDataOutputStream

字符流 (Character Streams)
  • 基础类:Reader 和 Writer

  • 文件操作:FileReaderFileWriter

  • 缓冲流:BufferedReaderBufferedWriter

  • 转换流:InputStreamReaderOutputStreamWriter

2. 按功能分类

节点流 (Node Streams)
  • 直接与数据源连接的流

  • 示例:FileInputStreamFileReader

处理流 (Processing Streams)
  • 对节点流或其他处理流进行包装

  • 提供额外功能(缓冲、数据类型转换等)

  • 示例:BufferedInputStreamBufferedReader

二、主要流类的用途

字节流用途

  1. FileInputStream/FileOutputStream

    • 用于读写二进制文件

    • 适合图像、音频、视频等非文本文件

  2. BufferedInputStream/BufferedOutputStream

    • 提供缓冲功能,减少I/O操作次数

    • 提高读写性能

  3. DataInputStream/DataOutputStream

    • 读写基本数据类型和字符串

    • 保持数据的原始格式

  4. ObjectInputStream/ObjectOutputStream

    • 用于对象的序列化和反序列化

字符流用途

  1. FileReader/FileWriter

    • 用于读写文本文件

    • 自动处理字符编码

  2. BufferedReader/BufferedWriter

    • 提供缓冲功能

    • BufferedReader特有的readLine()方法

  3. InputStreamReader/OutputStreamWriter

    • 字节流与字符流之间的桥梁

    • 可以指定字符编码

三、性能比较与最佳实践

性能比较

  1. 无缓冲 vs 缓冲流

    • 无缓冲流每次读写都直接操作底层资源,性能较差

    • 缓冲流通过内存缓冲区减少I/O操作次数,性能显著提升

    • 典型缓冲区大小:8KB (可调整)

  2. 字节流 vs 字符流

    • 处理文本时字符流性能更好(避免了字节-字符转换)

    • 处理二进制数据必须使用字节流

  3. 大文件处理

    • 缓冲流对大型文件性能提升更明显

    • 对于超大文件,考虑使用内存映射文件(MappedByteBuffer)


实践分析

  1. 始终使用缓冲流

    // 不好的做法FileInputStream fis = new FileInputStream(\"file.txt\");// 好的做法InputStream is = new BufferedInputStream(new FileInputStream(\"file.txt\"));
  2. 正确处理字符编码

    // 指定UTF-8编码Reader reader = new InputStreamReader( new FileInputStream(\"file.txt\"), StandardCharsets.UTF_8);
  3. 使用try-with-resources确保资源释放

    try (BufferedReader br = new BufferedReader(new FileReader(\"file.txt\"))) { String line; while ((line = br.readLine()) != null) { // 处理每一行 }}
  4. 根据场景选择合适的流

    • 文本处理:字符流

    • 二进制数据:字节流

    • 网络通信:缓冲流 + 适当设置缓冲区大小

  5. 大文件处理优化

    • 使用NIO的FileChannelMappedByteBuffer处理超大文件

    • 分块读取处理,避免内存溢出


性能测试

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流可以显著影响应用程序的性能和可靠性。