FileWriter写中文易乱码、不落盘、不支持UTF-8,应改用OutputStreamWriter+FileOutputStream指定UTF-8编码,或Files.write配合StandardCharsets.UTF_8;必须用try-with-resources确保自动flush和close。

FileWriter 能写字符串,但默认不落盘、不支持 UTF-8、不自动追加——直接用它写中文或日志很容易出错。
为什么 FileWriter.write() 后文件还是空的
因为 write() 只把数据塞进缓冲区,不调用 close() 或 flush() 就不会真正写入磁盘。常见现象是程序跑完,文件大小为 0 或内容缺失。
- 即使加了
flush(),若没close(),仍可能泄漏文件句柄 - JVM 退出时可能隐式刷盘,但不可靠;崩溃或强制终止就丢数据
- 手写
try...finally关流容易漏判null或嵌套异常
正确做法是用 try-with-resources:
try (FileWriter fw = new FileWriter("log.txt")) {
fw.write("启动完成\n");
} catch (IOException e) {
e.printStackTrace();
}
这个写法会在离开 try 块时自动 flush() + close(),不用手动干预。
覆盖写入和追加写入的区别在哪
行为由构造函数第二个参数决定,不是靠方法名或变量名区分:
-
new FileWriter("data.txt")→ 覆盖模式:文件存在则清空重写(极易误删历史) -
new FileWriter("data.txt", true)→ 追加模式:光标移到末尾,新内容接在后面 - 传错类型(比如传
"true"字符串)会编译失败,别硬绕
日志类场景务必显式传 true,否则每次重启都覆盖上一条记录。
写中文乱码?FileWriter 不支持指定编码
FileWriter 没有接受 Charset 的构造方法,它永远用 Charset.defaultCharset():
- Windows 默认是 GBK → 写 UTF-8 中文变乱码
- Linux/macOS 默认常是 UTF-8 → 看似正常,但跨平台部署就崩
- 无法通过系统属性或环境变量可靠统一
替代方案是组合 OutputStreamWriter + FileOutputStream:
try (OutputStreamWriter writer = new OutputStreamWriter(
new FileOutputStream("utf8.txt"), StandardCharsets.UTF_8)) {
writer.write("你好,世界!");
}
这才是真正可控、可移植的写法。别为了少敲两行代码赌平台默认编码。
字符数组写入比字符串更高效吗
不必然。write(char[]) 和 write(String) 底层都会转成 char[],差异只在是否多一次 String.toCharArray() 拷贝。
- 已有现成
char[](如从BufferedReader.read(char[])来),直接用write(char[])省掉拷贝 - 普通字符串拼接场景,用
write(String)更自然,JVM 优化足够好 - 不要为了“底层”硬转数组,除非 profiling 确实卡在这里
真正影响性能的是缓冲策略——FileWriter 本身无缓冲,BufferedWriter 才有;但 try-with-resources 下用后者也只需包一层。
最易被忽略的点:不是怎么调 write(),而是构造时要不要 true、编码能不能信、关流有没有交托给 JVM。这三个判断错了任意一个,文件内容就不可靠。










