必须显式指定UTF-8字符集,即使用OutputStreamWriter(OutputStream out, String charsetName)构造方法并传入"UTF-8",配合try-with-resources自动管理资源,避免乱码和资源泄漏。

直接用 OutputStreamWriter 包裹 FileOutputStream,并在构造时显式传入 "UTF-8" 字符集名,就能确保写入文件时使用 UTF-8 编码,避免中文等字符出现乱码。
必须显式指定字符集,不能依赖平台默认
OutputStreamWriter 有两个常用构造方法:
-
new OutputStreamWriter(OutputStream out)—— 使用系统默认编码(Windows 常为 GBK,Linux/macOS 多为 UTF-8),极易导致跨平台乱码 -
new OutputStreamWriter(OutputStream out, String charsetName)—— 显式指定编码,推荐使用"UTF-8"
务必选第二个,例如:
new OutputStreamWriter(new FileOutputStream("test.txt"), "UTF-8")
推荐搭配 try-with-resources 自动关闭资源
文件流和写入器都需及时关闭,否则可能内容未刷出或句柄泄漏。用 try-with-resources 最安全:
try (FileOutputStream fos = new FileOutputStream("data.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8")) {
osw.write("你好,世界!\n");
osw.write("Hello, World!");
} catch (IOException e) {
e.printStackTrace();
}
这样 osw 和 fos 都会在块结束时自动关闭,且 osw 关闭时会自动 flush 并调用底层 fos.close()。
立即学习“Java免费学习笔记(深入)”;
注意:不要重复调用 flush() 和 close() 混淆
在 try-with-resources 中,无需手动 flush() 或 close() —— 它们由 JVM 自动触发。如果手动调用,可能引发 IOException(如已关闭后再 close)。
- 需要立即写入磁盘(比如日志实时可见)?可在写操作后加
osw.flush(),但不是必须 - 不用手动
osw.close()或fos.close(),交给 try-with-resources - 若不用 try-with-resources,必须按
osw.close()→fos.close()顺序关闭(osw.close()已包含flush()和fos.close())
验证是否真用了 UTF-8
写完后可用命令行或编辑器确认:
- Linux/macOS:执行
file -i test.txt,输出应含charset=utf-8 - Windows:用记事本打开 → “另存为”,右下角编码显示应为“UTF-8”
- VS Code 或 IntelliJ:右下角状态栏会显示当前文件编码,点击可切换/重新加载
如果显示 ANSI、GBK 或 ISO-8859-1,说明写入时没指定 UTF-8,或被其他工具误转码了。


















