缓冲流通过内存缓冲区批量处理IO,显著减少系统调用次数、提升性能;需包装在FileInputStream/FileOutputStream外,推荐try-with-resources自动管理,注意flush与close时机及缓冲区大小设置。

直接用 FileInputStream 或 FileOutputStream 读写文件,每次操作都可能触发一次系统调用,频繁访问磁盘会让程序变慢。加一层 BufferedInputStream 或 BufferedOutputStream,相当于在内存里放了个“中转站”,数据先批量进出这个站,再统一和磁盘打交道,性能提升非常明显。
怎么创建和使用缓冲流
它们是装饰器,必须套在已有的节点流外面。常见写法如下:
- 读取时:用 FileInputStream → BufferedInputStream 包装
- 写入时:用 FileOutputStream → BufferedOutputStream 包装
- 推荐用 try-with-resources 自动关闭,避免资源泄漏
示例(复制文件):
try (FileInputStream fis = new FileInputStream("src.bin");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("dst.bin");
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
int b;
while ((b = bis.read()) != -1) {
bos.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
缓冲区大小怎么设才合适
默认是 8192 字节(8KB),对大多数场景够用。但不是越大越好,也不是越小越灵:
立即学习“Java免费学习笔记(深入)”;
- 小文件或随机读写:默认值通常最优,改小反而增加填充次数
- 大文件顺序读写:可适当增大(如 32KB 或 64KB),减少 fill() 调用频次
- 内存受限环境:避免盲目设到几百KB,缓冲区全在堆内存里
- 不建议设低于 1KB,否则起不到明显缓冲效果
别忘了 flush 和 close 的作用
BufferedOutputStream 写完数据不会立刻落盘,而是等缓冲区满、显式 flush() 或 close() 时才真正写出:
- 如果写完没 close 也没 flush,数据可能还卡在内存里,文件看起来是空的或不完整
- close() 会自动 flush,所以用 try-with-resources 是最稳妥的做法
- 需要确保中间结果及时可见(比如日志实时落盘),就手动调用 flush()
什么时候其实不需要缓冲流
不是所有场景都适合加缓冲:
- 数据量极小(比如只读几个字节),加缓冲反而多一层开销
- 底层流本身已带缓冲(如某些网络 Socket 流、加密流),再套一层意义不大
- 要求严格实时响应(如低延迟通信),缓冲会引入不可控延迟
- 配合 mark/reset 使用时要注意:marklimit 默认等于缓冲区大小,读太多会失效



















