核心思路是将多次小写攒成一次大写以减少系统调用和磁盘寻道;需合理设置缓冲区大小(默认8kb),关键数据写完立即flush,避免冗余包装,并用try-with-resources确保close。

用 BufferedOutputStream 减少磁盘 IO 的核心思路是:**把多次小写操作攒成一次大写,避开频繁的系统调用和磁盘寻道开销**。它本身不减少总数据量,但显著降低底层 write() 调用次数和上下文切换成本。
缓冲区大小要合理设置
默认缓冲区是 8192 字节(8KB),对多数场景够用,但不是绝对最优:
- 写大量小块数据(如日志逐行写入)→ 可适当增大(如 64KB),减少 flush 次数
- 内存敏感或单次写入已较大(如 >64KB)→ 缓冲意义变小,甚至可省略 Buffer 层
- 不要盲目设到几 MB:缓冲区全在堆内存里,过大易触发 GC,且延迟写入风险上升(异常时未 flush 的数据会丢失)
主动 flush 的时机比自动更重要
BufferedOutputStream 在缓冲区满、调用 flush() 或 close() 时才真正落盘。别依赖“写完就安全”:
- 关键数据写完后立即
flush()(如配置文件保存、事务日志落盘) - 长周期写入(如导出大文件)中定期 flush(比如每写 1MB 或每 1000 条记录),防 OOM 和断电丢数据
-
close()会自动 flush,但必须确保执行到(建议 try-with-resources)
避免包装无意义的流链
不是套越多层 Buffer 就越快。常见误区:
- FileOutputStream → BufferedOutputStream → ObjectOutputStream:只有最外层 Buffer 有效,ObjectOutputStream 内部也有缓冲,再包一层 Buffer 增加对象开销,收益极小
- 已用 NIO 的
FileChannel+ByteBuffer:再套 BufferedOutputStream 是冗余的,NIO 自身已做缓冲和零拷贝优化 - 确认目标流是否已缓冲:如
Files.newOutputStream()返回的是未缓冲的,适合加 Buffer;而某些框架封装的输出流可能自带缓冲
配合 try-with-resources 确保及时释放
BufferedOutputStream 本身不占操作系统句柄,但其包装的底层流(如 FileOutputStream)会。没 close 可能导致文件句柄泄漏:
try (FileOutputStream fos = new FileOutputStream("data.bin");
BufferedOutputStream bos = new BufferedOutputStream(fos, 32 * 1024)) {
bos.write(data); // 多次写
bos.flush(); // 关键点:确保落盘
} // 自动 close → flush + 释放 fos
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











