readLine() 读到文件末尾返回 null,须在循环条件中判空;应使用 try-with-resources 确保自动关闭;它兼容各种换行符,无需手动处理;默认 8KB 缓冲区通常足够,字符集和线程安全更需关注。

为什么不能直接用 readLine() 而不处理 null?
很多初学者写 bufferedReader.readLine() 时习惯用 while (true) 或忽略返回值判断,结果程序卡死、跳过末尾行,甚至抛 NullPointerException。因为 readLine() 读到文件末尾时明确返回 null,不是空字符串 "",也不是抛异常。
正确做法是把 readLine() 的返回值直接用于循环条件:
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}- 括号不能少:赋值表达式必须加括号,否则
!=优先级高于=,会编译失败 - 不要先调一次再进循环:避免重复读取第一行或漏掉某行
- 注意编码:如果文件是 UTF-8 但没指定,Windows 上默认用 GBK,中文会乱码
如何确保资源释放不漏掉 close()?
BufferedReader 底层包装了 FileInputStream 或 FileReader,不关会导致句柄泄漏,尤其在频繁读文件的工具类里容易触发 IOException: Too many open files。
推荐用 try-with-resources(Java 7+)自动关闭:
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream("data.txt"), "UTF-8"))) {
String line;
while ((line = reader.readLine()) != null) {
// 处理 line
}
} catch (IOException e) {
e.printStackTrace();
}- 不用手动调
reader.close(),即使循环中 throw 异常也会执行关闭 - 如果传入的是已打开的
InputStream,关闭BufferedReader会连带关闭它——这点常被误以为要单独关底层流 - 别在 finally 里再 close 一次,可能报
IOException: Stream closed
遇到换行符不统一(\r\n / \n / \r)怎么办?
readLine() 内部已兼容所有主流换行符:\n(Unix/Linux)、\r\n(Windows)、\r(老 Mac),它会把它们都截掉,只返回纯文本内容。你不需要自己 replaceAll("\r", "")。
但要注意两个边界情况:
- 最后一行没换行符时,
readLine()仍能正常读出该行(不会丢) - 文件以
\r结尾且前面无内容(比如只有回车),readLine()返回空字符串"",不是null - 如果业务需要保留原始换行信息,就不能用
readLine(),得改用read(char[])配合InputStream
性能上要不要自己调大 BufferedReader 的缓冲区?
默认缓冲区大小是 8192 字节(8KB),对绝大多数文本文件够用。除非你确定文件全是超长行(比如单行几 MB 的日志或 JSON),否则没必要动它。
如果真要调,构造时传第二个参数即可:
new BufferedReader(reader, 64 * 1024) // 64KB 缓冲区
- 缓冲区过大浪费内存,过小导致频繁系统调用,影响吞吐
- 实测显示:普通日志文件(平均行长 100–500 字符),8KB 和 64KB 性能差异不到 3%
- 真正瓶颈往往在磁盘 I/O 或字符串处理逻辑,而不是这个缓冲值
实际项目里最常踩的坑,是忘了指定字符集,或者在多线程环境下复用同一个 BufferedReader 实例——它不是线程安全的。

















