filereader/filewriter 默认使用平台编码(如windows的gbk),未指定字符集时读写中文会乱码,应改用inputstreamreader/outputstreamwriter显式指定"utf-8"编码。

为什么 FileReader / FileWriter 一读中文就乱码
因为 FileReader 和 FileWriter 默认用平台编码(Windows 是 GBK,Mac/Linux 通常是 UTF-8),不指定字符集,跨环境必出问题。它们底层其实是用 InputStreamReader 和 OutputStreamWriter 包装了字节流,但把编码参数硬写死了。
实际开发中,只要文件编码不是当前系统默认编码,就会出现 ??? 或方块 —— 这不是数据丢了,是解码时“认错了门牌号”。
- 永远别直接用
FileReader/FileWriter处理含中文的文本文件 - 显式使用
InputStreamReader+FileInputStream,并传入"UTF-8"等明确编码 - 同理,写入用
OutputStreamWriter+FileOutputStream,别漏掉编码参数
如何用 InputStreamReader 正确读取 UTF-8 文件
关键在构造时传对编码名,且必须和文件真实编码一致。常见错误是写了 "utf8"(少横线)或 "UTF8"(JVM 不认),正确写法是 "UTF-8"。
try (InputStream is = new FileInputStream("data.txt");
InputStreamReader reader = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(reader)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line); // 中文正常显示
}
}
- 编码名区分大小写,
"utf-8"可以,"UTF8"会抛UnsupportedEncodingException - 如果不确定文件编码,先用命令行工具查:Linux/macOS 用
file -i data.txt,Windows 可用 VS Code 打开看右下角编码标识 -
BufferedReader套一层只是为提升性能,不影响编码逻辑
写入时 OutputStreamWriter 的 BOM 陷阱
UTF-8 文件本身不需要 BOM,但某些 Windows 应用(如记事本)依赖它识别编码。Java 的 OutputStreamWriter 默认不写 BOM —— 这是对的;但如果你手动写入 \uFEFF,又没注意它在 UTF-8 下是 3 字节 EF BB BF,就可能让后续解析出错。
- 绝大多数场景下,**不要主动加 BOM**,尤其服务端生成 JSON/CSV 时,BOM 会导致解析失败(如
JSON.parse()报错Unexpected token \uFEFF) - 真要兼容记事本,可先写 BOM 再写内容:
out.write("\uFEFF"); out.write("你好");,但需确保OutputStreamWriter编码确实是"UTF-8" - 用
Files.newBufferedWriter(Paths.get("f.txt"), StandardCharsets.UTF_8)更安全,它不带 BOM 且 API 更简洁
跨语言协作时编码声明必须显式传递
Java 程序读写文件时用了 "GBK",而 Python 脚本默认按 UTF-8 打开,双方都“觉得自己没错”,结果数据一来一回就变乱码。这不是 Java 的 bug,是协作契约缺失。
- 文本文件应统一约定编码(推荐 UTF-8),并在文档、配置、甚至文件名后缀里注明(如
config_gbk.txt) - 网络传输文本(如 HTTP 响应体)必须带
Content-Type: text/plain; charset=UTF-8,否则接收方只能猜 - IDE(如 IntelliJ)需同步设置:File → Settings → Editor → File Encodings → Project Encoding 改为 UTF-8,且勾选 “Transparent native-to-ascii conversion” 防止 .properties 文件异常
编码问题本质是信息传递的上下文错位。最易被忽略的点是:你以为文件是 UTF-8,其实它是 ANSI(即系统默认编码);你以为程序指定了编码,其实被某层封装悄悄覆盖了。盯住每一处流的创建点,亲手写死 "UTF-8",比依赖默认值可靠得多。










