InputStreamReader的ready()方法判断底层输入流是否准备好提供字节数据且解码后大概率产生字符,而非字符缓冲区是否有字符;它依赖InputStream.available()并结合解码器状态粗略估算,不解析编码、不预解码、不检查字符边界。

InputStreamReader 的 ready() 方法并不判断“转换缓冲区中是否有可读字符”,而是判断底层输入流是否**已准备好提供字节数据**,且这些字节经解码后**大概率能产生至少一个可用字符**。
ready() 的实际行为
该方法本质是调用底层 InputStream 的 available()(若支持),再结合当前解码器状态做粗略估算:
- 它不解析编码(如 UTF-8 多字节序列)、不预解码、也不检查字符边界;
- 如果底层流返回
available() > 0,且当前解码器没有未完成的多字节序列(比如 UTF-8 中只读到半个汉字),ready()才可能返回true; - 若底层流阻塞(如网络流无数据、文件末尾刚过),或解码器正等待更多字节补全一个字符(如 UTF-8 中只读到
0xE4,还需两个字节),ready()就返回false。
为什么不能靠它判断“缓冲区有字符”
InputStreamReader 内部有两个层级缓冲:
- 字节缓冲区:从 InputStream 读取原始字节,供解码器使用;
-
字符缓冲区(隐式):解码器将字节转为字符后暂存,供
read()返回; -
ready()不暴露字符缓冲区是否非空,它只关心“现在调用read()是否大概率不阻塞”——这取决于字节是否够解出下一个字符,而非字符是否已解好。
更可靠的替代方式
若需确认是否有字符可读,应直接尝试非阻塞读取:
立即学习“Java免费学习笔记(深入)”;
- 用
read(char[] cbuf, int off, int len)并设len=1,配合setReadTimeout()(需包装为BufferedInputStream+ 自定义逻辑); - 对文件等确定长度的流,优先用
BufferedReader,其ready()更稳定(内部维护字符缓冲); - 业务上避免轮询
ready(),改用一次read()判断返回值:-1表示流结束,>= 0表示读到字符。
典型误用场景
以下代码不可靠:
❌ 错误写法(可能死循环或漏读):while (reader.ready()) { // ready() 可能反复返回 true,但 read() 仍阻塞
char c = (char) reader.read(); // 实际仍可能阻塞
}
正确做法是:
✅ 推荐写法:int ch;
while ((ch = reader.read()) != -1) {
process((char) ch);
}


















