Files.write安全写入日志需显式指定StandardOpenOption.APPEND和CREATE,手动添加换行符,捕获IOException,多线程下须同步,可选SYNC/DYSNC保障落盘,推荐使用成熟日志框架。

用 Files.write 安全写入日志,关键不是“只写一次”,而是确保内容完整、不覆盖旧日志、线程安全且异常可追溯。直接调用 Files.write 默认会覆盖文件,日志场景下必须显式控制打开选项和写入行为。
用 StandardOpenOption.APPEND 追加而非覆盖
日志必须累积记录,不能每次重写整个文件。StandardOpenOption.APPEND 保证内容追加到文件末尾,避免丢失历史日志。
- 不加该选项,默认行为是
CREATE+TRUNCATE_EXISTING,即清空重写 - 务必同时指定
StandardOpenOption.CREATE,否则目标文件不存在时会抛NoSuchFileException - 示例:
Files.write(path, line.getBytes(UTF_8), CREATE, APPEND)
加上 StandardOpenOption.SYNC 或 StandardOpenOption.DSYNC 保障落盘
普通写入只到操作系统页缓存,断电或崩溃可能导致最后几条日志丢失。SYNC/DYSNC 强制内核将数据(及元数据/仅数据)刷入磁盘。
-
SYNC:同步数据 + 文件属性(如修改时间),更严格,性能略低 -
DSYNC:仅同步数据,适用于多数日志场景,兼顾可靠性与吞吐 - 注意:Windows 对
DYNC支持有限,生产环境建议优先用SYNC
避免多线程并发写入冲突
Files.write 本身不是线程安全的,多个线程同时调用可能造成日志错乱(如两行内容交织)。需外部同步:
立即学习“Java免费学习笔记(深入)”;
- 推荐用
ReentrantLock或synchronized包裹写入逻辑,粒度控制在单次写操作 - 不要锁整个日志方法(影响吞吐),也不要锁整个文件对象(无意义)
- 更优方案:使用
java.util.logging、Log4j 或 SLF4J + Logback 等成熟日志框架,它们已内置异步缓冲、文件滚动和线程安全写入
始终指定字符编码并捕获异常
省略编码易导致中文乱码;忽略异常会让日志失败静默,排查困难。
- 强制用
StandardCharsets.UTF_8,别依赖平台默认编码 - 捕获
IOException并记录错误(例如写入失败时打印到控制台或备用日志),不能吞掉异常 - 小技巧:写入前检查父目录是否存在,用
Files.createDirectories(path.getParent())预创建,避免因目录缺失失败


















