使用缓冲流(如bufferedoutputstream、bufferedwriter)可批量写入减少系统调用,需显式flush或close确保落盘,避免单字节频繁写、不关闭流或滥用flush导致缓冲失效,高可靠场景应结合force()、临时文件原子重命名及校验机制。

核心思路是让数据先在内存里“攒一攒”,等够一批再统一写入磁盘,而不是每写一点就敲一次硬盘。
用对缓冲流是第一步
别直接用 FileOutputStream 或 FileInputStream,它们每次 write() 或 read() 都可能触发一次系统调用。换成带缓冲的版本:
-
BufferedOutputStream和BufferedInputStream:适合字节流,默认 8KB 缓冲区,小写自动聚合 -
BufferedWriter和BufferedReader:适合字符流,支持按行读写,内部也自带缓冲
构造时可自定义缓冲大小(比如 new BufferedOutputStream(out, 64 * 1024)),大文件或高吞吐场景下适当调大能进一步减少 flush 次数。
写完记得 flush 或 close
缓冲区不会自己主动倒空——它只在三种情况下才真正落盘:
- 缓冲区满了(自动触发)
- 你显式调用
flush() - 你调用
close()(内部会先 flush 再关闭)
如果写完忘了 close 或 flush,程序退出时缓冲区数据就丢了,文件内容不完整。尤其在日志、配置写入等关键场景,务必确保资源释放。
避免“假缓冲”操作
用了缓冲流不代表一定高效,这些做法会让缓冲失效:
- 每写一个字节就调一次
flush()—— 相当于手动拆掉缓冲层 - 用
write(int)循环写单字节却不批量处理 —— JVM 方法调用开销变大,缓冲收益被抵消 - 频繁创建/销毁缓冲流对象 —— 缓冲区初始化和 GC 带来额外负担
推荐批量写入:把多条记录拼成字符串或 byte[] 一次性 write(),或者用 StringBuilder 组装后再输出。
大文件或高频写入时再加一层保障
仅靠 Java 层缓冲还不够,操作系统页缓存和磁盘易失缓存仍可能导致断电丢数据。对可靠性要求高的场景:
- 用
FileChannel配合force(false)强制刷盘(同步元数据和内容) - 覆写关键文件时,采用“写临时文件 + 原子 rename”方式,避免中间态损坏
- 搭配 CRC/xxHash 校验值,写入时生成、读取时验证,提前发现静默损坏
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











