filereader 不能指定编码是因为它内部固定使用 charset.defaultcharset(),而该默认编码随系统或jvm参数变化易致乱码;应改用 inputstreamreader 配合 fileinputstream 显式传入 standardcharsets.utf_8 等标准编码常量。

FileReader 本身不支持指定 Charset,它是基于平台默认编码的字符流,无法直接传入编码参数。如果需要按指定编码(如 UTF-8、GBK)读取文本文件,应改用 InputStreamReader 配合 FileInputStream。
为什么 FileReader 不能指定编码
FileReader 是 InputStreamReader 的子类简化封装,其构造方法只接受 File 或 String 路径,内部自动使用 Charset.defaultCharset() —— 这在不同系统或 JVM 启动参数下可能变化(如 Windows 上常为 GBK,Linux/macOS 上多为 UTF-8),极易导致乱码。
正确做法:用 InputStreamReader + FileInputStream
手动组合字节流与字符流,显式传入所需 Charset:
- 先用
FileInputStream打开文件(负责字节读取) - 再用
InputStreamReader包装它,并传入StandardCharsets.UTF_8等标准编码对象 - 最后可套上
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);
}
}
更简洁写法(Java 7+ 推荐)
利用 Files.newBufferedReader,一行创建带指定编码的缓冲读取器:
Path path = Paths.get("data.txt");
try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
br.lines().forEach(System.out::println);
}
该方法底层仍是 InputStreamReader + FileInputStream,但封装更安全、简洁,且自动处理路径和异常。
常见编码选择提醒
-
StandardCharsets.UTF_8:推荐用于新项目、跨平台文件 -
StandardCharsets.GBK:读取 Windows 记事本保存的中文旧文件时常用 -
StandardCharsets.ISO_8859_1:极少用,仅用于某些遗留协议或单字节编码场景 - 避免用字符串名(如
"UTF-8")直接构造,易拼错或抛UnsupportedEncodingException;优先用StandardCharsets中的静态常量
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











