java中reader读取字符流时,唯一可靠判断末尾的方式是read()返回-1;返回≥0为有效字符,绝不会返回null;其他如ready()、readline()返回null或捕获异常均不可靠。

在 Java 中,Reader 读取字符流时,**不能依赖返回值是否为 null 或空字符串来判断流末尾**,因为 read() 方法返回的是 int 类型的字符码(0–65535),而末尾的唯一可靠标志是返回 -1。
read() 方法返回 -1 表示流已结束
Reader.read()(无参重载)每次读取一个字符,成功时返回该字符的 Unicode 值(≥ 0),读到流末尾时返回 -1。这是 Javadoc 明确规定的契约,也是唯一标准方式:
- 返回值为
-1→ 确认已到末尾,后续调用仍会返回-1 - 返回值 ≥ 0 → 是有效字符,可安全转为
char(如(char) c) - 返回值绝不会是
null(因为返回类型是int)
避免常见误判方式
以下做法不可靠,容易出错:
- 检查
readLine()返回null后就认为流结束 —— 正确,但仅适用于BufferedReader,且null表示“无更多行”,不等价于底层流末尾(比如最后一行没换行符时可能漏读) - 用
ready()判断“是否还有数据” —— 它只表示“当前是否可非阻塞读取”,返回false不代表已到末尾(可能只是暂时没数据或缓冲为空) - 捕获
IOException当作结束信号 —— 异常表示错误,不是正常结束;流正常关闭不会抛异常
推荐的安全读取模式
循环读取直到 -1 是最通用、最健壮的方式:
int ch;
while ((ch = reader.read()) != -1) {
// 处理字符 (char) ch
}
若需批量读取(更高效),使用带缓冲数组的 read(char[] cbuf):
- 返回值为实际读取的字符数(≥ 0),读到末尾时返回
-1 - 即使数组未填满,只要返回值 > 0,就说明读到了有效字符
- 只有返回
-1才代表流彻底结束
注意 close() 和资源释放
close() 不影响末尾判断逻辑,但它会释放资源并使后续读取抛 IOException。因此:
- 末尾判断必须在
close()之前完成 - 建议用 try-with-resources 自动关闭,但判断逻辑仍以
-1为准 - 不要用是否能调用
close()来反推是否到末尾










