FileInputStream/FileOutputStream适合二进制文件复制,需用try-with-resources关闭;应配合BufferedInputStream/BufferedOutputStream提升性能;文本文件优先用Files工具类并显式指定UTF-8编码。

用 FileInputStream 和 FileOutputStream 读写二进制文件最直接
如果只是复制图片、PDF 或任意非文本文件,用字节流最稳妥,不会因编码问题损坏内容。
常见错误是忘记关闭流或未处理异常导致资源泄漏。Java 7+ 推荐用 try-with-resources 自动释放:
try (FileInputStream fis = new FileInputStream("input.bin");
FileOutputStream fos = new FileOutputStream("output.bin")) {
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
} catch (IOException e) {
// 处理异常
}
-
fis.read()返回int,但实际只用低 8 位,读到末尾返回-1 - 单字节循环效率低,生产环境应改用
byte[]缓冲区(如new byte[8192])配合read(byte[])和write(byte[], int, int) - 不要用
FileOutputStream覆盖关键文件前不加确认 —— 它默认会清空原文件
读写文本文件优先选 Files.readAllLines() 和 Files.write()
Java 7 引入的 Files 工具类封装了字符编码和资源管理,比手动套 InputStreamReader + BufferedReader 简洁得多。
典型场景:读取配置、日志行、CSV 片段。注意编码必须显式指定,否则依赖系统默认(Windows 是 GBK,Linux/macOS 通常是 UTF-8):
立即学习“Java免费学习笔记(深入)”;
Listlines = Files.readAllLines(Paths.get("data.txt"), StandardCharsets.UTF_8); Files.write(Paths.get("result.txt"), "hello".getBytes(StandardCharsets.UTF_8));
-
readAllLines()会把整个文件加载进内存,大文件(>100MB)慎用,改用Files.lines()流式处理 -
write()默认覆盖,追加需传入StandardOpenOption.APPEND - 路径用
Paths.get()构造,别拼接字符串 ——"dir\\file.txt"在 Linux 下会失败
BufferedInputStream / BufferedOutputStream 不是可选,是必需
裸用 FileInputStream 或 FileOutputStream 性能极差,每次 read() 都触发一次系统调用。缓冲流通过内存块中转,大幅减少 I/O 次数。
即使你用 Files 类,底层也默认启用了缓冲;但自己构造流时容易漏掉:
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("large.zip"));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("copy.zip"))) {
// 使用 bis.read(buffer) 和 bos.write(buffer, 0, len)
}
- 缓冲区大小不一定要 8192 —— 小文件用 1024,大文件可设 65536,但超过 64KB 后收益递减
-
BufferedOutputStream的flush()必须在 close() 前显式调用(除非确定 close() 会触发 flush),否则最后一批数据可能丢失 - 不要对已包装的流再套一层缓冲流(如
new BufferedInputStream(new BufferedInputStream(...))),徒增开销
中文乱码本质是编码不匹配,不是流类型选错
用 FileReader 读中文出 ?,大概率是因为它默认用平台编码解码,而文件实际是 UTF-8。这不是“应该换字节流”,而是要统一编码声明。
正确做法:弃用 FileReader/FileWriter(它们无法指定编码),改用带 Charset 的构造方式:
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream("utf8.txt"), StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
-
FileReader是InputStreamReader的子类,但屏蔽了编码参数,属于历史包袱 - IDE 中看到文件是乱码,先右键 → “File Encoding” 确认真实编码,再让代码匹配
- 网络传输或跨平台场景下,UTF-8 是唯一安全选择;GBK 只适用于 Windows 本地旧系统










