核心目的是显式指定字符编码以避免默认编码跨平台不一致导致乱码或异常,推荐用files.newbufferedreader(path, standardcharsets.utf_8)配合try-with-resources确保安全简洁。

用 Files.newBufferedReader 替代 new BufferedReader(new FileReader(...)) 的核心目的,是显式指定字符编码,避免依赖系统默认编码(如 Windows 上的 GBK、Linux/macOS 上的 UTF-8)导致读取乱码或 MalformedInputException 等报错。
明确指定 UTF-8 编码,杜绝默认编码陷阱
经典写法 new FileReader(file) 内部使用 Charset.defaultCharset(),而该值不可控且跨平台不一致。改用 Files.newBufferedReader 时必须传入标准编码,最常用的是 StandardCharsets.UTF_8:
Files.newBufferedReader(Paths.get("data.txt"), StandardCharsets.UTF_8)- 不再依赖环境,无论在哪台机器运行,都按 UTF-8 解析字节流
- 若文件实际是 GBK 编码,此处需换为
Charset.forName("GBK"),但务必确保与文件真实编码一致
配合 try-with-resources 自动释放资源
新 API 天然支持自动关闭,无需手动 finally 块,代码更简洁安全:
- ✅ 推荐写法:
try (BufferedReader reader = Files.newBufferedReader(path, UTF_8)) {<br> String line;<br> while ((line = reader.readLine()) != null) {<br> // 处理行<br> }<br>} - ❌ 避免老式写法:
FileReader fr = new FileReader("data.txt"); // 编码不确定<br>BufferedReader br = new BufferedReader(fr); // 易出错
处理非 UTF-8 文件时,编码名要准确拼写
有些旧文件用 GB2312、GBK、ISO-8859-1 等编码,此时不能硬写 UTF_8,而要用 Charset.forName(...) 并捕获 UnsupportedCharsetException:
Charset charset = Charset.forName("GBK");- 注意大小写:用
"GBK",不是"gbk"或"GbK"(虽然多数 JVM 宽松,但规范写法更稳妥) - 可先用工具(如
file -i filename或 IDE 编码探测)确认真实编码,再写死进代码
与 Files.lines 配合实现函数式读取
如果只需逐行处理,Files.lines 更简洁,底层也基于 newBufferedReader:
Files.lines(path, StandardCharsets.UTF_8).forEach(System.out::println);- 注意:返回的是
Stream<string></string>,必须消费(如forEach、collect)或显式close(),否则可能泄露资源 - 推荐在
try中使用,或确保 stream 被终端操作终结











