必须手动 flush 是因为 bufferedoutputstream 默认攒满 8192 字节才写出,若程序异常退出、关键日志需实时落盘或协议头需立即被接收方解析,未 flush 的数据会滞留内存而丢失;正确做法是 bos.flush() 立即写出当前缓冲内容,之后仍可继续 write。

调用 BufferedOutputStream 的 flush() 方法就能强制把缓冲区里还没写出去的数据立即推到底层流(比如文件或网络连接),确保数据真正落盘或可被接收方看到。
为什么必须手动 flush
BufferedOutputStream 默认会攒够缓冲区大小(默认 8192 字节)才一次性写出。如果程序中途异常退出、或写完关键数据后没等到缓冲区满,这部分数据就还卡在内存里,没真正写入目标设备——也就是“没落地”。
- 程序可能抛出未捕获异常,提前终止,
close()根本没机会执行 - 日志写完一条重要错误,需要立刻落盘,不能等缓冲区满
- 向网络服务端发送协议头(header),对方要马上解析,不能延迟
怎么正确调用 flush
拿到 BufferedOutputStream 实例后,直接调用 flush() 即可。它不关闭流,也不清空缓冲区结构,只把当前已缓存的内容全部写出。
bos.flush(); // 立即刷新,之后还能继续 write- 如果配合
try-with-resources,close()会自动触发一次flush(),但那是最后一步;想提前确认,就得手动调
典型安全写入模式
下面这段代码兼顾了关键点:header 写完立刻刷出,保证结构完整;payload 后依赖 close() 自动刷,减少冗余调用。
try (FileOutputStream fos = new FileOutputStream("data.bin");
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
bos.write("HEADER".getBytes());
bos.flush(); // 强制 header 落地
bos.write("PAYLOAD...".getBytes());
// 不再手动 flush,close 时自动完成
} catch (IOException e) {
e.printStackTrace();
}
不用 try-with-resources 时的注意事项
如果自己管理资源,务必在 finally 块中先 flush() 再 close():
-
flush()确保数据写出 -
close()内部也会再刷一次,属于双重保障,且释放系统资源 - 顺序不能反:先 flush,再 close;否则 close 可能来不及刷就中断了
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











