关键在于统一编码源头、显式指定字符集、避免依赖默认值。java字符串内部用unicode,但文件、网络等外部数据源使用具体编码,乱码本质是“用错的编码解字节”,只要读写两端编码一致即可确保中文正确显示。

关键在于**统一编码源头、显式指定字符集、避免依赖默认值**。Java 中字符串内部用 Unicode,但文件、网络、控制台等外部数据源用的是具体编码(如 UTF-8、GBK)。乱码本质是“用错的编码解字节”,只要读写两端用同一套规则,就能稳住中文。
确认并匹配原始数据的编码格式
不能猜,要查实:
- 读文件前,用编辑器(如 VS Code、Notepad++)右下角查看保存编码;若用
Files.write()写入,必须记清用了StandardCharsets.UTF_8还是Charset.forName("GBK") - 处理 HTTP 响应时,看响应头
Content-Type: text/plain; charset=utf-8 - 读控制台输入:Windows 命令行默认 GBK,Linux/macOS 默认 UTF-8;IDE 运行配置里也需留意 VM 参数是否设了
-Dfile.encoding=UTF-8
用 InputStreamReader / OutputStreamWriter 显式传参
别用 FileReader 或 FileWriter 的无参构造——它们隐式调用 Charset.defaultCharset(),极不可靠。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 推荐写法(类型安全):
new InputStreamReader(is, StandardCharsets.UTF_8) - 也可用字符串名(注意规范):
new InputStreamReader(is, "UTF-8");禁用"utf8"、"gb2312"等非标准写法,可能抛异常 - 写文件同理:
new OutputStreamWriter(os, StandardCharsets.UTF_8)
搭配 BufferedReader / BufferedWriter 并用 try-with-resources
InputStreamReader 本身不缓冲,直接读效率低且不便按行处理。
- 包装成
BufferedReader后可稳定调用readLine() - 务必用 try-with-resources 自动关闭所有层:
InputStream→InputStreamReader→BufferedReader - 示例:
try (FileInputStream fis = new FileInputStream("data.txt"); InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8); BufferedReader br = new BufferedReader(isr)) { String line; while ((line = br.readLine()) != null) { System.out.println(line); // 此时已是正确解码的字符串 } }
避开常见陷阱
很多乱码不是编码错了,而是流程绕过了编码控制:
- 别混用字节流和字符串构造:
new String(bytes, "UTF-8")要比先fis.read(bytes)再手动转更可控;但不如直接走InputStreamReader流程清晰 - 别在多环节切换编码:比如文件用 UTF-8 写,却用 GBK 构造
InputStreamReader,再输出到 UTF-8 控制台——中间一步已损坏 - 慎用
RandomAccessFile.readLine():它固定用 ISO-8859-1 解码,读中文必乱,应改用getBytes()+new String(..., "GBK")手动转 - IDE 项目编码设置(如 Eclipse/IDEA 的 Text file encoding)只影响新建文件和编译,不影响运行时读取已有文件的逻辑,别指望它“一键修复”旧文件乱码
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










