必须显式指定字符集,避免依赖jvm默认编码导致跨平台乱码;推荐用standardcharsets常量或字符串(如"utf-8")传入inputstreamreader构造函数,并配合try-with-resources确保资源释放。

直接用 InputStreamReader 包装字节流时,若不显式指定字符集,它会依赖 JVM 默认编码(如 Windows 上常为 GBK,Linux/macOS 上多为 UTF-8),导致同一份文件在不同系统上读取出现乱码。解决的关键是**始终手动传入明确的 Charset 或字符集名称**。
明确指定字符集名称(推荐字符串方式)
这是最常用、可读性最好的做法。把字符集名作为字符串传入 InputStreamReader 构造函数:
- 读取 UTF-8 编码的文件(最通用):
new InputStreamReader(new FileInputStream("data.txt"), "UTF-8") - 读取 GBK 编码的旧版中文 Windows 文件:
new InputStreamReader(new FileInputStream("log.txt"), "GBK") - 注意大小写不敏感,但建议统一用大写(如
"UTF-8"而非"utf-8"),避免部分旧 JDK 版本兼容问题
使用 Charset 类型参数(类型安全,适合 Java 7+)
借助 StandardCharsets 提供的静态常量,编译期即可校验字符集是否合法,避免拼写错误:
new InputStreamReader(new FileInputStream("config.json"), StandardCharsets.UTF_8)new InputStreamReader(new FileInputStream("readme.txt"), StandardCharsets.ISO_8859_1)- 这种方式不会抛出
UnsupportedEncodingException,更健壮;如果需支持自定义字符集(如 GB18030),仍可用Charset.forName("GB18030")
避免踩坑:不要依赖平台默认编码
以下写法看似简洁,实则埋下跨平台隐患:
-
new InputStreamReader(new FileInputStream("file.txt"))—— 使用 JVM 默认编码,行为不可控 -
new InputStreamReader(System.in)—— 控制台输入也受系统环境影响,应明确指定(如StandardCharsets.UTF_8) - 即使源文件本身是 UTF-8,若在 GBK 系统上运行且未指定编码,仍会按 GBK 解码,造成中文变问号或乱码
配合 try-with-resources 确保资源释放
手动指定编码的同时,别忘了及时关闭流,推荐用自动资源管理:
try (InputStreamReader reader = new InputStreamReader(
new FileInputStream("notes.txt"), StandardCharsets.UTF_8)) {
BufferedReader br = new BufferedReader(reader);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
这样既指定了编码,又避免了流泄露,代码清晰可靠。











