fileoutputstream.flush()是空操作,不触发落盘;真正落盘需close()或getfd().sync();缓冲链路中仅bufferedoutputstream.flush()有效清空应用层缓冲,fsync()才推进至设备层。

FileOutputStream 的 flush() 操作在硬件存储层面**没有实际意义**——它不会触发数据落盘,也不保证写入物理介质。
FileOutputStream.flush() 本质上是空操作
该方法继承自 OutputStream,源码中只是一个空实现:
public void flush() throws IOException {}它不调用系统 write(),不刷新内核缓冲区,也不向磁盘发送同步指令。无论你调多少次 fos.flush(),只要没关流、也没用 getFD().sync(),数据就仍可能只停留在 JVM 内存或操作系统页缓存中。
真正影响硬件写入的是 close() 或 sync()
-
close()会隐式调用一次 flush(对 FileOutputStream 仍是空操作),但更重要的是:它最终触发系统close()系统调用,此时内核通常会把关联文件的脏页排队写入块设备(但依然不保证立即落盘) - 要强制落盘,必须显式调用:
fos.getFD().sync();
这会发起fsync()系统调用,阻塞直到所有已写入内核缓冲区的数据及元数据(如文件大小、修改时间)都持久化到物理存储介质
缓冲区层级决定了 flush 是否有效
只有带应用层缓冲的装饰器流(如 BufferedOutputStream)才让 flush() 有意义:
- BufferedOutputStream.flush() → 把自己内存 buffer 中的数据写入底层流(比如 FileOutputStream)
- 但底层如果是 FileOutputStream,这步仍然只是把字节交给内核,不等于写进磁盘
- 所以完整链路要落盘,需:
bufferedOut.flush();
fos.getFD().sync();
硬件视角:从字节到磁盘的三道关卡
一个字节从 Java 写出到真正刻录进 SSD/NAND 或磁盘扇区,需经过:
- ① JVM 内存缓冲(如 BufferedOutputStream 的 buf[])→
flush()可清空这一层 - ② 操作系统页缓存(Page Cache)→
fos.write()默认只到这里;fsync()才推进到下一步 - ③ 设备控制器与物理介质(含磁盘缓存、SSD FTLC、掉电保护电容等)→ 即使
fsync()返回,某些廉价设备仍可能谎报完成;真容错需硬件级支持(如带电容的 SSD)











