filereader读中文会乱码,因其默认使用平台编码(windows为gbk,linux/macos多为utf-8),不支持显式指定编码,导致utf-8文件在gbk环境解码失败;必须改用inputstreamreader包装fileinputstream并传入"utf-8",且需try-with-resources确保流关闭。

FileReader 适合读取纯文本,但必须注意编码和资源释放,否则容易乱码或文件句柄泄漏。
为什么 FileReader 读中文会乱码?
FileReader 是基于平台默认编码的字符流,不支持显式指定编码(如 UTF-8)。Windows 默认是 GBK,Linux/macOS 默认是 UTF-8 —— 如果文件用 UTF-8 保存,而在 Windows 上用 FileReader 直接读,IOException 不一定报,但内容大概率是乱码。
- 不要依赖
FileReader处理含中文、emoji 或跨平台分发的文本文件 - 真正可控的方式是用
InputStreamReader包装FileInputStream,并传入"UTF-8" - 如果确定文件全是 ASCII 字符(如日志 ID、配置键名),且运行环境编码统一,
FileReader才勉强可用
如何安全地用 FileReader 读一行?
FileReader 本身不提供按行读取能力,必须配合 BufferedReader。单独 new FileReader("a.txt") 只能逐字符读,效率低且易出错。
- 正确组合:
new BufferedReader(new FileReader("a.txt")) - 务必调用
readLine(),而不是read()—— 后者返回 int,需手动转 char,还容易漏掉换行符逻辑 - 遇到空行时
readLine()返回"",不是null;只有到文件末尾才返回null
不关流会怎样?
FileReader 和 BufferedReader 都是资源型对象,底层持有文件句柄。不关闭会导致:
- Windows 下可能无法删除或重命名该文件(“进程正在使用”)
- 大量文件读取后触发
java.io.IOException: Too many open files - 即使 JVM 退出,句柄也不一定立即释放,影响长期运行服务
推荐写法(Java 7+):
try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}这样无论是否异常,br 和其包装的 FileReader 都会被自动关闭。
用 FileReader 的本质是妥协——它省了一行构造代码,却把编码和资源管理的坑留给了你。真要读文本,优先选 Files.readAllLines(Paths.get("x.txt"), StandardCharsets.UTF_8);非要流式读,就老实用 InputStreamReader + 显式编码。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











