filewriter的flush()方法不能保证数据立即落盘,仅将java缓冲区数据写入操作系统page cache;真正落盘需用fileoutputstream.getchannel().force(true)或files.write()配合standardopenoption.sync。

FileWriter 的 flush() 方法**不能保证数据立即落盘到物理磁盘**,它只确保将 Java 内存缓冲区中的数据写入操作系统内核的缓冲区(page cache),是否真正写入磁盘由操作系统控制。
flush() 的真实作用
flush() 主要完成两件事:
- 把 FileWriter 自身的 Java 层缓冲区(如 BufferedWriter 包装时的内部 char 数组)内容,通过底层 OutputStreamWriter → FileOutputStream 逐级写出;
- 最终调用
FileOutputStream.getFD().sync()—— 但注意:**FileWriter 本身不自动调用 sync(),只有在调用flush()且底层是 FileOutputStream 时,JDK 实现中可能触发 sync,但这不是规范保证,且 JDK 版本和实现有差异。** 实际上,标准 FileWriter(无包装)的flush()通常只做到内核缓冲区,不强制刷盘。
真正落盘的可靠方式
要确保数据写入物理磁盘(即“落盘”),必须显式调用操作系统级的同步操作:
-
使用 FileOutputStream + getChannel().force(true):这是最常用且跨平台的方式。
示例:FileOutputStream fos = new FileOutputStream("a.txt");<br> fos.write("hello".getBytes());<br> fos.getChannel().force(true); // true 表示同时同步文件数据和元数据(如修改时间)<br> fos.close(); -
使用 Files.write() 配合 StandardOpenOption.SYNC:
Files.write(Paths.get("a.txt"), "hello".getBytes(),<br> StandardOpenOption.CREATE, StandardOpenOption.WRITE,<br> StandardOpenOption.SYNC); // 每次写都落盘 - 慎用 FileWriter + flush() + close():close() 会隐式 flush(),但仍只到内核缓冲区。某些系统或文件系统(如 ext4 默认 data=ordered)可能在 close 后不久落盘,但不实时、不可控、不保证。
为什么 flush() 不等于落盘?
这是 I/O 分层设计决定的:
- Java 层缓冲 → 操作系统 page cache(
flush()到达此处)→ 磁盘控制器缓存 → 物理磁盘; - 操作系统为性能会延迟写入磁盘(几秒到几十秒),除非收到
fsync()(Java 中对应FileChannel.force())或fdatasync()系统调用; - 断电或崩溃时,仅调用
flush()的数据大概率丢失。
实际建议
- 普通日志或非关键数据:用
BufferedWriter+flush()即可,兼顾性能与基本可靠性; - 金融、事务、审计等关键数据:必须用
FileChannel.force(true)或StandardOpenOption.SYNC; - 避免混用 FileWriter 和 FileOutputStream 操作同一文件,易引发缓冲错乱或覆盖;
- 频繁 force() 会显著降低写入性能,按需使用(如每条关键记录后 force,而非每次字符都 force)。










