只需关闭最外层流即可确保刷盘安全和资源释放,因为BufferedOutputStream的close()会先flush再调用被包装流的close(),形成自外而内的链式关闭;反向关闭会导致Stream closed异常。

Java中 BufferedOutputStream 嵌套多层包装流时,只需关闭最外层流即可确保刷盘安全和资源释放,无需手动逐层关闭。核心在于理解其装饰器本质和 close() 方法的内部行为。
关闭顺序:外层优先,自动向下传播
BufferedOutputStream 继承自 FilterOutputStream,其 close() 方法明确包含 out.close() 调用(其中 out 就是它所包装的底层流)。这意味着:
- 调用
bos.close()会先执行flush()刷出缓冲区数据,再调用被包装流(如FileOutputStream)的close() - 若底层流本身也是包装流(例如
OutputStreamWriter包装FileOutputStream),该链式关闭会继续向下传递 - 反向操作——先关
FileOutputStream再关BufferedOutputStream——会导致后续bos.close()抛出IOException: Stream closed
刷盘安全的关键:close() 自带 flush + 底层落盘保障
BufferedOutputStream 的 close() 不仅释放资源,更强制完成数据持久化:
-
close()内部先调用flush(),把内存缓冲区所有字节写入下层流 - 下层流(如
FileOutputStream)的close()会触发操作系统级刷盘(或至少确保内核缓冲区提交),这是数据真正写入磁盘的最后一步 - 因此,只要最外层
BufferedOutputStream正常关闭,就不会出现“文件大小为0”这类数据丢失问题
推荐做法:用 try-with-resources 替代手工管理
手动判断 null、嵌套 try-catch 容易出错,现代 Java(7+)应直接使用自动资源管理:
立即学习“Java免费学习笔记(深入)”;
- 所有包装流(
BufferedOutputStream、OutputStreamWriter、FileOutputStream)都实现AutoCloseable - JVM 按声明逆序自动关闭:先关
BufferedOutputStream,再关OutputStreamWriter,最后关FileOutputStream - 即使中间某步抛异常,后续流仍会被正常关闭,避免资源泄漏
try (FileOutputStream fos = new FileOutputStream("out.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
BufferedOutputStream bos = new BufferedOutputStream(osw)) {
bos.write("data".getBytes());
}
什么情况下需要显式 flush()?
绝大多数场景下,close() 已足够。但以下情况建议在 close() 前加 flush():
- 程序需确认数据已到达下层流(例如调试时观察临时文件内容)
- 写入后不立即关闭流,而是继续其他耗时操作,希望提前释放缓冲区内存
- 使用非标准包装流(自定义实现未严格遵循规范),无法完全信任其
close()行为


















