解决中文乱码的关键是明确源头编码、显式指定字符集、避免依赖平台默认值:1. 必须用带Charset参数的InputStreamReader构造器;2. 确保输入流未被提前消费;3. 推荐组合BufferedReader使用;4. Web场景需解析HTTP响应头中的charset。

用 InputStreamReader 解决中文乱码,关键不是“怎么转”,而是**明确源头编码、显式指定字符集、避免依赖平台默认值**。Java 默认使用系统编码(如 Windows 的 GBK),而网络或文件常为 UTF-8,不匹配就必然乱码。
1. 必须显式传入 Charset,别用无参构造
这是最常见也最致命的错误。以下写法极大概率乱码:
❌ 错误示例:
InputStreamReader reader = new InputStreamReader(inputStream); // 用系统默认编码,不可靠
正确做法是根据数据来源,**主动指定 Charset**:
- 读取 UTF-8 编码的网络响应、JSON 文件、现代文本:用
StandardCharsets.UTF_8 - 读取旧版 Windows 环境生成的文本(如记事本另存为“ANSI”):可能是
Charset.forName("GBK")或"GB2312" - 不确定编码?先用工具(如
file -i、Notepad++ 编码识别)确认,再写死 Charset
2. 输入流本身不能被提前消费
InputStreamReader 是装饰器,它包装的是原始字节流。如果在创建 reader 前,你已经调用了 inputStream.read()、inputStream.mark() 或其他读取操作,流指针已移动,reader 会从中间开始解码,导致开头乱码甚至异常。
确保:原始流在传给 InputStreamReader 之前,**未被任何方式读取或标记过**。
3. 配合 BufferedReader 使用更安全高效
单独用 InputStreamReader 只能按字符读(read()),效率低且不便。推荐组合 BufferedReader:
InputStream is = ...; // 来源:FileInputStream / URLConnection.getInputStream()
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line); // 中文正常显示
}
注意:关闭时只需关最外层(br.close()),它会自动关闭内部的 isr 和底层流。
4. Web 场景要特别注意 HTTP 响应头
比如用 HttpURLConnection 获取网页内容:
- 先检查响应头
Content-Type,例如text/html; charset=utf-8→ 提取utf-8 - 若响应头没指定 charset,默认按规范应为 ISO-8859-1,但中文网页几乎都是 UTF-8,所以建议 fallback 到 UTF-8
- 更稳妥做法:用
URLConnection.getContentType()解析 charset,再传给InputStreamReader
不复杂但容易忽略 —— 显式指定编码 + 保证流干净 + 合理封装,中文就读得稳。

















