第 12 章 · 输入输出(IO)

12.1 IO 流概述

Java 用“流(Stream)”抽象数据的输入输出。按数据单位分字节流字符流,按方向分输入流输出流

  • 字节流:InputStream / OutputStream(处理二进制)。
  • 字符流:Reader / Writer(处理文本,自动处理编码)。

12.2 字节流

try (InputStream in = new FileInputStream("a.bin");
     OutputStream out = new FileOutputStream("b.bin")) {
    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) != -1) {
        out.write(buf, 0, len);
    }
}
  • FileInputStream/FileOutputStream 读写文件;read() 返回 -1 表示读完。
  • 缓冲流 BufferedInputStream/BufferedOutputStream 包装底层流,减少磁盘 IO 次数。
  • 装饰设计模式:缓冲流包装普通流,动态增强功能而不改原类。

12.3 字符流

try (BufferedReader br = new BufferedReader(new FileReader("a.txt"));
     BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        bw.write(line);
        bw.newLine();
    }
}
  • FileReader/FileWriter 读写字符;BufferedReader.readLine() 按行读取。
  • 转换流 InputStreamReader/OutputStreamWriter 在字节流与字符流间转换,可指定编码。

12.4 其他 IO 流

  • 对象流ObjectInputStream/ObjectOutputStream 实现序列化(对象需 implements Serializable)。
  • 数据流DataInputStream/DataOutputStream 读写基本类型(readInt/writeUTF 等)。
  • 打印流PrintStream/PrintWriterSystem.out 就是 PrintStream)。
  • 内存流ByteArrayInputStream/ByteArrayOutputStreamCharArrayReader/CharArrayWriter 操作内存而非磁盘。
  • SequenceInputStream:串联多个输入流。

12.5 File 类

File 表示文件/目录的路径,提供 existscreateNewFilemkdirdeletelistFilesisDirectory 等操作。

12.6 随机访问文件

RandomAccessFile 支持按位置读写(seek),适合在文件任意位置跳转。

12.7 字符编码

字符集规定字符与字节的映射:ASCII、GBK、UTF-8(变长,兼容 ASCII)、UTF-16 等。读写时需编码一致,否则乱码:

new InputStreamReader(in, StandardCharsets.UTF_8);

12.8 与其他语言对比

  • Cfopen/fread/fwrite 基于文件指针,需手动关闭、手动管理缓冲区,无异常机制。
  • C++iostreamcin/cout)运算符重载流式,也有 fstream
  • Pythonopen()/with 极简,自动关闭;with 语句 ≈ Java 的 try-with-resources。

关键差异:Java 用“装饰器模式”堆叠流(如缓冲流包文件流),灵活但类多、啰嗦;Python 的 open 一个函数搞定。Java 的 try-with-resources 自动关闭流,避免了 C 式忘记 close 的资源泄漏。