Java IO流体系本质是围绕“数据流动”构建的分层抽象,核心在于理解流向(输入/输出)、单位(字节/字符)、角色(节点/处理)三层逻辑;File类仅管理路径与元数据,不参与读写;字节流(InputStream/OutputStream)处理二进制,字符流(Reader/Writer)专用于文本并涉及编码;装饰器模式通过组合实现功能扩展。
Java IO流体系本质是围绕“数据流动”构建的一套分层抽象,核心不是记住所有类名,而是理解三层逻辑:流向(输入/输出)、单位(字节/字符)、角色(节点/处理)。File类不属流体系,它只管路径和元数据;真正负责读写的,是基于InputStream/OutputStream和Reader/Writer的两类流。
流向决定方向:InputStream 和 Reader 是“往程序里拉数据”,OutputStream 和 Writer 是“把数据推出去”。别混淆——读文件用 FileInputStream 或 FileReader,写文件用 FileOutputStream 或 FileWriter。
单位决定适用场景:字节流(InputStream/OutputStream)处理一切二进制内容,图片、PDF、jar包都靠它;字符流(Reader/Writer)专为文本设计,内部自动处理编码转换,但只适合纯文本(如 .txt、.csv、.json)。
角色决定是否直接操作文件:FileInputStream 是节点流,直连磁盘文件;BufferedInputStream 是处理流,必须套在 FileInputStream 外面才能用,它不自己打开文件,只给已有流加缓冲能力。
立即学习“Java免费学习笔记(深入)”;
File 类只做三件事:表示路径(new File("a.txt"))、查状态(exists()、length()、isDirectory())、做文件系统操作(mkdirs()、delete()、renameTo())。它不读不写内容,也不涉及编码。真正读写时,你得把 File 对象传给 FileInputStream 或 FileReader 构造器。
常见误用:试图用 File 对象直接获取文件内容——不行。它只是“路牌”,不是“运输车”。
FileReader/FileWriter 看似简单,但默认使用系统编码(Windows 是 GBK),极易导致中文乱码。生产环境几乎不用它们直接构造。
正确做法是组合使用:
例如读 UTF-8 文本:
try (BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream("data.txt"), StandardCharsets.UTF_8))) {
String line;
while ((line = br.readLine()) != null) { ... }
}
IO 流强大之处不在单个类,而在组合能力。比如要安全高效读一个带中文的文本文件,典型链条是:
写入同理:FileOutputStream → OutputStreamWriter → BufferedWriter。每加一层,就增加一项能力(编码转换、缓冲、格式化等),且各层职责单一,可自由拆装。
不需要死记 BufferedInputStream 是谁的子类,只需知道:它必须包装一个 InputStream 才能工作,作用就是加缓冲。