Files.writeString() 写中文乱码主因是未显式指定StandardCharsets.UTF_8,而字符串源可能为GBK等编码;且该方法不自动创建父目录,路径不存在会抛NoSuchFileException。

Files.writeString() 是 Java 11 引入的便捷方法,能一行代码完成文本写入,但直接用容易踩编码、路径、异常处理的坑。
为什么 Files.writeString() 写出来的文件中文乱码?
默认使用 StandardCharsets.UTF_8,但仅当字符串本身是 UTF-8 编码且系统终端/编辑器也按 UTF-8 解析时才显示正常。常见乱码实际是读取端问题,但更隐蔽的问题是:你没显式指定 charset,而调用方字符串可能来自非 UTF-8 源(比如旧版 GBK 控制台输入)。
- 务必显式传入
StandardCharsets.UTF_8,不要依赖默认值 - 如果目标环境强制要求 GBK(如某些 Windows 老工具),改用
Charset.forName("GBK") - 验证方式:用
Files.readString(path, StandardCharsets.UTF_8)读回,看是否与原文一致
Files.writeString() 的第三个参数 options 有哪些实用组合?
这个 java.nio.file.StandardOpenOption 数组控制底层文件操作行为,不是可有可无的装饰项。
- 追加写入:传入
StandardOpenOption.APPEND—— 注意它不会自动换行,需手动在字符串末尾加"\n" - 覆盖写入(默认行为):不传或只传
StandardOpenOption.CREATE+StandardOpenOption.TRUNCATE_EXISTING - 原子写入防中断:搭配
StandardOpenOption.WRITE和StandardOpenOption.CREATE即可,JVM 底层已保证基本原子性;真要强一致性,得用临时文件 +Files.move()
路径不存在时会报 java.nio.file.NoSuchFileException 吗?
会。和 Files.readAllBytes() 不同,Files.writeString() **不会自动创建父目录** —— 它只负责写文件内容,不负责建路径。
- 必须提前调用
Files.createDirectories(Paths.get("/tmp/log"))创建完整父路径 - 别用
new File(...).mkdirs(),那是遗留 API,和 NIO 路径语义不一致 - 推荐封装成工具方法:
Files.createDirectories(path.getParent()),再调用writeString
最易忽略的是路径权限和文件锁:Windows 下若目标文件正被记事本打开,会抛 AccessDeniedException;Linux 下若父目录不可写,createDirectories 就会失败 —— 这些都不是 writeString 本身的错,但错误堆栈第一行总指向它。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











