Java中解决乱码的核心是显式指定字符编码,如new InputStreamReader(in, "UTF-8"),并确保读写两端编码一致,同时配合try-with-resources自动关闭资源。

Java 中用 InputStreamReader 和 OutputStreamWriter 解决乱码问题,核心是**显式指定字符编码**。默认使用系统平台编码(如 Windows 的 GBK),而文件或网络数据常为 UTF-8,不匹配就乱码。只要在构造时传入正确的 Charset 或编码名,就能准确解码/编码。
明确指定编码,避免依赖平台默认值
不写编码参数会走 Charset.defaultCharset(),极易出错。务必显式传入如 "UTF-8":
new InputStreamReader(inputStream, "UTF-8")new OutputStreamWriter(outputStream, "UTF-8")- 推荐用
StandardCharsets.UTF_8(类型安全、无异常):new InputStreamReader(in, StandardCharsets.UTF_8)
读写两端编码必须一致
读取文件用 UTF-8,写入也得用 UTF-8;若源文件是 GBK,读写都得用 GBK。常见错误是“读用 UTF-8,写用默认”,导致二次乱码。
- 确认源数据真实编码(可用记事本另存为查看,或用
file -i命令) - 读写代码中编码字符串保持完全一致,大小写敏感(
"utf-8"和"UTF-8"都可,但建议统一用大写) - 网络响应(如 HTTP)需从
Content-Type头获取 charset,例如text/html; charset=ISO-8859-1
配合 try-with-resources 自动关闭,防止资源泄漏
这两个类是装饰器,底层依赖字节流。未关闭可能导致缓冲区未刷新、文件句柄占用等问题:
- 用
try (Reader r = new InputStreamReader(in, UTF_8)) { ... }确保自动 close - 不要只关外层 writer/reader 就完事——它们的 close 会级联关闭底层流
- 避免手动调用
flush(),除非需立即写出(close 内部已 flush)
注意 BOM(字节顺序标记)对 UTF-8 的影响
某些编辑器保存 UTF-8 文件时会加 BOM(EF BB BF),InputStreamReader 默认不识别它,可能把开头当乱码。可手动跳过:
- 读取前检查前 3 字节是否为 BOM,是则 skip
- 或用第三方库如 Apache Commons IO 的
BOMInputStream - 更稳妥做法:统一要求源文件无 BOM,或用
Files.newBufferedReader(path, UTF_8)(JDK 7+ 自动处理 BOM)
不复杂但容易忽略。关键就两点:编码显式指定 + 读写端一致。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











