BufferedOutputStream通过内存缓冲与合理刷盘合并小写操作,降低系统调用和磁盘延迟;默认8KB缓冲减少IO次数,需避免频繁flush、及时close,并依场景调整缓冲大小,但不保证立即落盘。

用 BufferedOutputStream 加速写入,核心不是“减少磁盘 IO 次数”本身,而是通过**内存缓冲 + 合理触发刷盘**,把多次小写操作合并成更少、更大的物理写入,从而降低系统调用开销和磁盘寻道/旋转延迟。
缓冲区如何降低实际IO频率
每次调用 write(int) 或 write(byte[]) 时,BufferedOutputStream 默认先写入内部字节数组(默认 8192 字节),不立刻落盘。只有当缓冲区满、显式调用 flush()、或流关闭时,才把整块数据一次性交给底层 FileOutputStream,最终由操作系统决定是否真正写入磁盘(可能还受页缓存影响)。
举例:连续写 100 个 1 字节数据 —— 不用缓冲,就是 100 次系统调用;用默认 8KB 缓冲,大概只需 1–2 次真正落盘(取决于 OS 缓存策略)。
关键操作要点
- 不要每写一次就 flush():这会让缓冲失效,等同于裸写,甚至更慢(多一次方法调用开销)
- 关闭前务必 close() 或显式 flush():否则缓冲区剩余数据会丢失
-
根据写入模式选缓冲大小:默认 8KB 适合多数场景;若批量写大块数据(如导出日志、生成文件),可设为 64KB 或 128KB(
new BufferedOutputStream(fos, 65536)),减少 flush 次数 - 避免在循环内新建 BufferedOutputStream:每次 new 都分配缓冲区、关联底层流,开销大;应复用同一个实例
它不能解决什么
BufferedOutputStream 是用户态缓冲,不控制磁盘调度或文件系统行为。它无法绕过操作系统页缓存,也不能保证数据立即落盘(force(true) 才能同步到磁盘)。如果需要强持久化(如金融交易日志),仍需配合 FileChannel.force(true) 或 RandomAccessFile.getFD().sync()。
一个典型安全写法
try (FileOutputStream fos = new FileOutputStream("data.bin");
BufferedOutputStream bos = new BufferedOutputStream(fos, 32768)) {
for (byte[] chunk : dataChunks) {
bos.write(chunk); // 数据进缓冲区
}
// close() 自动 flush + 关闭底层流,无需手动 flush()
}
这样既利用了缓冲合并写入,又确保资源释放和数据完整性。

















