PushbackInputStream的read()方法优先读取内部缓冲区字节,缓冲区为空时委托底层流读取并可能阻塞;unread()仅能退回已读字节,超容抛异常,且EOF后unread仍有效。

PushbackInputStream 的 read() 方法在缓冲区为空时,会直接委托给底层输入流读取一个字节,而不是阻塞等待或抛出异常。这是它区别于普通缓冲流的关键行为——它“先尝试回退区,再穿透到底层”。
缓冲区优先读取
每次调用 read() 时,PushbackInputStream 首先检查内部的 pushback 缓冲区(即已“退回”的字节):
- 如果缓冲区非空,直接返回缓冲区头部字节,并移动读指针;
- 缓冲区长度由构造时指定(默认为 1),超出容量调用
unread()会抛出IOException。
缓冲区为空时穿透底层流
当 pushback 缓冲区为空,read() 不会卡住,而是立即调用封装的 in.read()(即底层 InputStream 的 read 方法):
- 若底层流有数据可读,返回该字节(0–255);
- 若底层流已到末尾,返回
-1; - 若底层流阻塞(如网络流未就绪),当前线程会在此处阻塞,直到有数据、流关闭或发生 I/O 异常。
注意 unread() 与 read() 的配合边界
看似“可退回”,但实际使用中容易踩坑:
立即学习“Java免费学习笔记(深入)”;
-
unread(int b)只能退回一个字节(或字节数组),且必须在read()之后、下一次read()之前调用; - 连续多次
unread()超过缓冲区容量会失败; - 如果在
read()返回-1后调用unread(),该字节仍会被存入缓冲区——下次read()会先返回它,而非再次触发底层流 EOF。
典型用途:解析需要“窥探”的协议
比如解析以特定分隔符(如 '{' 或 '"')开头的 JSON 片段:
- 先
read()一个字节判断类型; - 若不是预期字符,用
unread(b)退回去,交由其他逻辑处理; - 整个过程不丢失原始字节,也不重复读取底层流。


















