pushbackinputstream 是 java 中用于回退已读字节的装饰器流,其核心是内部缓冲区(默认1字节),unread 操作将字节存入该缓冲区,后续 read 优先返回缓冲区数据;缓冲区满时抛 ioexception;多字节推回按数组索引逆序压入,需显式指定足够容量;不可 unread(-1),不支持重复 unread 同一位置,close 会丢弃未读缓冲数据。

PushbackInputStream 是 Java 中用于“回退”已读字节的装饰器流,它内部维护一个缓冲区(默认大小为 1 字节),允许你把刚读取的字节“推回去”,后续读取时会优先返回这些被推回的字节。
unread 的核心机制:缓冲区是关键
调用 unread(int b) 或 unread(byte[] b) 并不是真正把字节“塞回原始流”,而是把字节存入 PushbackInputStream 自己的内部缓冲区。下次调用 read() 时,它先检查缓冲区是否有数据,有就返回缓冲区里的字节,没有才委托给底层流读取。
注意:缓冲区大小有限(构造时可指定,默认为 1)。如果推回的字节数超过缓冲区容量,会抛出 IOException("Push back buffer is full")。
基本用法:单字节推回最常用
适合需要“试探性读取”的场景,比如解析协议头、跳过 BOM、或实现简单的词法分析。
- 先调用 read() 获取一个字节
- 判断该字节是否符合预期(如是否是某个分隔符、是否属于数字)
- 如果不合预期,调用 unread(b) 把它推回去,后续逻辑就能当作没读过一样继续处理
示例:
byte[] data = "Hello".getBytes();PushbackInputStream pbis = new PushbackInputStream(new ByteArrayInputStream(data));
int b = pbis.read(); // 读到 'H'
if (b == 'H') {
pbis.unread(b); // 推回 'H'
}
int c = pbis.read(); // 这里再次读到 'H',不是 'e'
多字节推回:需注意缓冲区大小和顺序
unread(byte[] b) 和 unread(byte[] b, int off, int len) 会将字节数组**按索引顺序从后往前**压入缓冲区(即数组末尾的字节最先被 read() 返回)。
例如:
unread(new byte[]{1, 2, 3}) → 缓冲区内容实际为 [3, 2, 1] → 下次 read() 先返回 3,再 2,再 1。
务必确保缓冲区足够大,否则会失败。建议构造时显式指定容量:
PushbackInputStream pbis = new PushbackInputStream(in, 8); // 支持最多推回 8 字节常见陷阱与注意事项
- 不能 unread(-1):-1 是 read() 的 EOF 标识,不是有效字节值,传入会抛 IllegalArgumentException
- unread 后不能再 unread 同一位置:缓冲区是栈式结构,重复 unread 会覆盖或溢出,不是“多次撤回”
- 底层流不感知 unread:推回操作完全在 PushbackInputStream 层完成,原始流的 position 不会倒退
- close() 会丢弃缓冲区内容:关闭前未读完的推回字节将丢失
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











