Java中的IO大总结

236 阅读3分钟

Java中的IO流就像水管系统,负责在程序和外部设备之间传输数据。为了更清晰理解,我们可以从三个维度分类,并配合生活化比喻:


一、按数据流向分类(水流方向)

  1. 输入流(读数据)

    • 像吸管吸水:InputStream(字节流)、Reader(字符流)
    • 场景:读取文件内容、接收网络数据
  2. 输出流(写数据)

    • 像水龙头放水:OutputStream(字节流)、Writer(字符流)
    • 场景:保存文件、发送网络请求

二、按数据类型分类(水管材质)

1. 字节流(万能水管)

  • 特点:能传输所有类型数据(图片、视频、文本等)
  • 基类InputStreamOutputStream
  • 常用类
    • FileInputStream:读取本地文件(如:new FileInputStream("cat.jpg")
    • FileOutputStream:写入本地文件(如保存下载的图片)
    • BufferedInputStream:带缓冲区(类似用货车批量运输,比卡车快)
  • 场景:处理二进制文件(如图片、压缩包)、网络数据传输

2. 字符流(专用文字水管)

  • 特点:自动处理字符编码(如UTF-8),适合文本
  • 基类ReaderWriter
  • 常用类
    • FileReader:读取文本文件(如new FileReader("note.txt")
    • FileWriter:写入文本文件(如记录日志)
    • BufferedReader:带缓冲+行读取(readLine()读整行)
  • 场景:处理纯文本(如CSV文件、配置文件)

三、按功能角色分类(水管配件)

1. 节点流(直连水源)

  • 特点:直接操作数据源,如文件、内存
  • 示例
    • FileInputStream(字节流直连文件)
    • FileReader(字符流直连文件)

2. 包装流(功能增强)

  • 特点:包裹其他流,扩展功能
  • 常见类型
    • 缓冲流(加速):BufferedInputStreamBufferedReader

      // 读取提速10倍以上
      try (BufferedReader br = new BufferedReader(new FileReader("bigfile.txt"))) {
          String line;
          while ((line = br.readLine()) != null) { /* 处理行 */ }
      }
      
    • 转换流(字节转字符):InputStreamReader(指定编码)

      // 解决中文乱码问题
      new InputStreamReader(new FileInputStream("data.txt"), "GBK");
      
    • 数据流(处理基本类型):DataInputStream(读写int、double等)

      DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.bin"));
      dos.writeInt(100); // 直接写整数
      
    • 对象流(序列化):ObjectInputStream(传输Java对象)

      // 保存对象
      ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"));
      oos.writeObject(user); // User需实现Serializable接口
      

四、选择流的决策树

  1. 处理什么数据?

    • 图片/视频/任意二进制 → 字节流
    • 文本(尤其是含中文) → 字符流
  2. 需要什么功能?

    • 基础读写 → 节点流(如FileInputStream
    • 需要缓冲 → +BufferedXXX
    • 处理Java基本类型 → DataXXX
    • 传输对象 → ObjectXXX
  3. 是否需要指定编码?

    • 是 → 用InputStreamReader/OutputStreamWriter

五、经典场景对比

场景推荐流组合原因
复制图片文件FileInputStream + FileOutputStream字节流保证二进制完整性
读取大型文本文件BufferedReader + FileReader缓冲提升读取速度,支持按行读取
保存用户配置(UTF8)FileWriter字符流自动处理编码(默认UTF8)
网络数据传输BufferedInputStream + 字节流缓冲减少网络IO次数
跨系统传输Java对象ObjectOutputStream序列化保持对象结构

六、避坑指南

  1. 资源泄漏:务必用try-with-resources自动关闭流

    try (FileInputStream fis = new FileInputStream("file.txt")) {
        // 自动关闭流
    }
    
  2. 乱码问题:字符流默认使用系统编码,跨平台时显式指定:

    new InputStreamReader(new FileInputStream("text.txt"), StandardCharsets.UTF_8);
    
  3. 缓冲流关闭顺序:只需要关闭最外层缓冲流,内层流会自动关闭。

通过理解这些分类和场景,就能像搭积木一样组合出适合当前需求的IO方案。