filereader 默认使用系统平台编码(如windows为gbk),无法指定编码,易致中文乱码;应使用inputstreamreader+fileinputstream或files.lines()并显式指定standardcharsets.utf_8。

Java 中用 FileReader 不能直接指定编码,因为它**默认使用系统平台默认编码**(如 Windows 是 GBK,macOS/Linux 通常是 UTF-8),容易导致中文乱码。所以,**不推荐用 FileReader 读取非系统默认编码的文本文件**。
为什么 FileReader 无法指定编码?
FileReader 是 InputStreamReader 的子类,但它只提供基于系统默认编码的构造方法,没有接受 Charset 或编码名的重载构造器。它的本质是:
new InputStreamReader(new FileInputStream(file))
而这个 InputStreamReader 没传编码,就自动用了 Charset.defaultCharset()。
正确做法:用 InputStreamReader + FileInputStream
要指定编码(比如 UTF-8),应绕过 FileReader,直接用 InputStreamReader 包装 FileInputStream:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 创建
FileInputStream读取字节流 - 用指定编码(如
StandardCharsets.UTF_8)构造InputStreamReader - 再套上
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);
}
} catch (IOException e) {
e.printStackTrace();
}
更简洁写法:Files.lines()(推荐用于简单场景)
JDK 7+ 提供了更现代、函数式的方式,一行代码读取所有行(自动关闭资源,指定编码):
- 返回
Stream<string></string>,适合过滤、映射等操作 - 必须显式传入
Charset,不会乱码
示例:
try (Stream<string> lines = Files.lines(Paths.get("data.txt"), StandardCharsets.UTF_8)) {
lines.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}</string>
补充提醒:避免踩坑
- 不要用
FileReader读取 UTF-8/BOM 文件——BOM 字节会被当成普通字符,可能影响解析 - 如果文件编码不确定,可用第三方库(如 Apache Tika 或 juniversalchardet)自动探测
- 写文件时也建议用
OutputStreamWriter显式指定编码,保持读写一致
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










