InputStreamReader 不判断编码,需确保代码使用的 Charset 与文件真实编码一致;可通过编辑器查看、BOM 检测或命令行工具确认编码,优先使用 Files.newBufferedReader 并传入 StandardCharsets.UTF_8 等标准常量。

InputStreamReader 本身不判断编码,只按你给的 Charset 去解释字节。所谓“误判为 ANSI”,其实是你写了 new InputStreamReader(in) 或硬写了 "GBK",而文件实际是 UTF-8(或反之)。修复核心就一条:**让代码用的编码和文件真实编码一致**。
确认文件真实编码
别靠猜测或系统默认值。常见方法:
- 用文本编辑器(如 Notepad++、VS Code)打开文件,看右下角显示的编码;
- 检查文件开头是否有 BOM:UTF-8 BOM 是
EF BB BF(对应字节数组-17, -69, -65),无 BOM 的 UTF-8 和 GBK 看起来一样,需结合内容判断; - 用命令行工具验证:Linux/macOS 下运行
file -i filename.txt,Windows 可用 PowerShell 的Get-Content -Encoding Byte查前几个字节。
按真实编码创建 InputStreamReader
一旦确认编码,直接传入对应 Charset:
- 文件是 UTF-8(含或不含 BOM):
new InputStreamReader(in, StandardCharsets.UTF_8); - 文件是 Windows 记事本“ANSI”保存(实际多为 GBK):
new InputStreamReader(in, "GBK")或Charset.forName("GBK"); - 文件是旧版西欧 ANSI(如 ISO-8859-1):
StandardCharsets.ISO_8859_1; - 不确定且需自动识别?可先读前 3 字节判断 BOM,再分支构造 reader,避免盲目试错。
推荐更安全的替代写法
绕过手动管理流和 reader 的风险:
立即学习“Java免费学习笔记(深入)”;
- 读文件优先用
Files.newBufferedReader(path, charset),它强制要求传 Charset,且自动关闭资源; - 如果必须用 FileInputStream,确保流未被提前读取——比如不要在 new InputStreamReader 前调
in.read()或in.mark(); - 避免用字符串名(如
"UTF-8")传编码,改用StandardCharsets.UTF_8,类型安全,不抛UnsupportedEncodingException。
常见误区提醒
这些操作不会“修复”乱码,只会让问题更隐蔽:
- 把 UTF-8 文件强行用 GBK 打开,再另存为 UTF-8——可能已损坏部分字符;
- 在代码里写死
"UTF-8"却不验证文件来源,尤其当文件由 Windows 用户手工生成时; - 用无参
InputStreamReader(in)依赖系统默认编码,跨平台必然出问题。


















