inputstreamreader 默认乱码是因为未指定字符集时依赖系统默认编码,与源数据编码不一致所致;必须显式传入standardcharsets.utf_8等确定编码,优先使用files.newbufferedreader防错。

为什么 InputStreamReader 默认会乱码
因为 InputStreamReader 构造时不显式指定字符集,它会调用 Charset.defaultCharset(),而这个值取决于运行时 JVM 所在操作系统的默认编码:Windows 通常是 GBK 或 MS932,Linux/macOS 一般是 UTF-8。一旦源数据(比如文件、网络流)的编码和这个默认值不一致,就必然出现乱码。
必须显式传入 Charset 参数
解决方式只有一条:永远不要依赖无参构造函数。哪怕你“确定”是 UTF-8,也要写死 StandardCharsets.UTF_8。
-
new InputStreamReader(inputStream, StandardCharsets.UTF_8)—— 推荐,类型安全,无异常 -
new InputStreamReader(inputStream, "UTF-8")—— 兼容老 JDK,但可能抛UnsupportedEncodingException - 避免
new InputStreamReader(inputStream)—— 这是绝大多数乱码的根源
读取文件时别只盯 InputStreamReader
如果源头是文件,更推荐直接用 Files.newBufferedReader(path, charset),它内部封装了 InputStreamReader + BufferedReader,且强制要求传 Charset,天然防错。
- 它比手拼
FileInputStream→InputStreamReader→BufferedReader更简洁、资源管理更可靠 - 路径为
Path类型,自动处理不同系统下的分隔符(/vs\),但编码仍需你指定 - 示例:
Files.newBufferedReader(Paths.get("data.txt"), StandardCharsets.UTF_8)
网络响应流(如 HTTP)更要小心编码来源
HTTP 响应头里的 Content-Type: text/html; charset=utf-8 才是真实编码依据,不能硬写 UTF-8。如果头里没声明或声明错误,得结合响应体 BOM 或内容特征判断。
- 用
HttpURLConnection时,先调conn.getContentEncoding()和conn.getContentType()解析 charset - 用 OkHttp 或 Apache HttpClient,它们通常已自动提取并设置 charset,但仍建议检查
response.body().string()的实际解码结果 - 遇到
或空格变方块,大概率是 charset 传错了,优先核对来源而非修改代码逻辑
最常被忽略的一点:即使你写了 StandardCharsets.UTF_8,如果原始字节流本身不是 UTF-8 编码(比如 Windows 记事本保存的 ANSI 文件),照样乱码——InputStreamReader 不做编码转换,它只是按你给的规则去解释字节。











