用 bufferedoutputstream 高效写大文件的关键是合理设置缓冲区大小并确保正确关闭:默认8kb适用于小文件,大文件推荐32kb或64kb;必须用try-with-resources保证flush;避免频繁flush、逐字节写和嵌套缓冲。

用 BufferedOutputStream 高效写大文件,核心就一条:让数据“攒够了再一起交出去”,而不是写一点就催操作系统一次。它不改变你要写的字节数,但能大幅减少系统调用次数——这才是提速的关键。
缓冲区大小要匹配实际场景
默认 8KB(8192 字节)够日常用,但写大文件时建议手动设为 32KB 或 64KB(即 32768 或 65536 字节)。这个尺寸既接近常见文件系统块大小(如 4KB 的整数倍),又能减少 flush 次数,实测吞吐常提升 15% 左右。别盲目设到 1MB:内存占用陡增、GC 压力变大,还可能因延迟落盘影响程序可靠性。
- 本地 SSD 写超 100MB 文件 → 用 32KB
- NFS 或高延迟存储 → 用 16KB 更稳
- 内存受限或小批量写 → 保持 8KB 即可
必须用 try-with-resources 确保数据落盘
BufferedOutputStream 的缓冲区只在 close()、flush() 或满时才真正写入磁盘。如果忘了 close(),程序异常退出,最后几千字节就永远丢在内存里。用 try-with-resources 能自动触发 close(),也就自动 flush(),是最稳妥的做法。
- 不要自己 new 出来又忘记关
- 别在循环里反复创建新实例——每次分配缓冲区+绑定流都是额外开销
- 追加写入记得传 true:
new FileOutputStream(file, true)
写法上避免抵消缓冲效果
缓冲的价值在于“合并小写”。一旦写法破坏这个逻辑,性能反而不如裸 FileOutputStream。
- 别在每条记录后调 bos.flush() —— 这等于每写一次就强制刷盘
- 别用 write(int) 逐字节写 —— 尽量用 write(byte[], off, len),哪怕数组只有几十字节也比单字节调用强
- 如果日志类关键数据不能丢,可在积攒一定条数(如 100 条)或事务提交点主动 flush(),而不是每条都 flush
和底层流配合要干净
BufferedOutputStream 是包装器,不是万能胶。它应该直接包 FileOutputStream,中间别再套一层缓冲流,也不要用 PrintStream 自动 flush 干扰节奏。
- ✅ 推荐:
new BufferedOutputStream(new FileOutputStream(f, true), 32768) - ❌ 避免:
new BufferedOutputStream(new BufferedOutputStream(...)) - ❌ 慎用:
new PrintStream(new BufferedOutputStream(...))(默认 auto-flush 会让缓冲失效)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











