该类继承自FilterInputStream
没有引入包
该类的类头注释如下:
/** * A <code>PushbackInputStream</code> adds * functionality to another input stream, namely * the ability to "push back" or "unread" * one byte. This is useful in situations where * it is convenient for a fragment of code * to read an indefinite number of data bytes * that are delimited by a particular byte * value; after reading the terminating byte, * the code fragment can "unread" it, so that * the next read operation on the input stream * will reread the byte that was pushed back. * For example, bytes representing the characters * constituting an identifier might be terminated * by a byte representing an operator character; * a method whose job is to read just an identifier * can read until it sees the operator and * then push the operator back to be re-read. * * @author David Connelly * @author Jonathan Payne * @since JDK1.0 */
大意如下:
PushbackInputStream为其他输入流添加了新功能,该功能提供了回推和取消读取一个字节的能力
在片段代码需要读取由特定分隔符分隔的不确定大小的数据时是很方便和有用的
在读到终止字符后,该代码片段可以取消读取该字符,因此下一个read操作将会重复读取被回推的该byte
例如,表示构成标识符字符的字节可能由表示操作符字符的字节终止;用于读取一个标识符的方法可以读取到遇到操作符为止,然后将该操作符推回以进行重读
该类含有如下的成员变量:
读取缓冲区
protected byte[] buf;
读取标志位:
protected int pos;
该类含有如下的成员方法:
检测流有效状态
private void ensureOpen() throws IOException { if (in == null) throw new IOException("Stream closed"); }
构造函数(给予输入流和缓冲区大小
public PushbackInputStream(InputStream in, int size) { super(in); if (size <= 0) { throw new IllegalArgumentException("size <= 0"); } this.buf = new byte[size]; this.pos = size; }
构造函数(默认缓冲区大小为1
public PushbackInputStream(InputStream in) { this(in, 1); }
读取方法(读出一个字节数据
public int read() throws IOException { ensureOpen(); if (pos < buf.length) {//当前缓冲区不为空 return buf[pos++] & 0xff; } return super.read();//缓冲区为空直接从流中读取 }
读取方法(读出数组数据
public int read(byte[] b, int off, int len) throws IOException { ensureOpen(); if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int avail = buf.length - pos;//缓冲区剩余数据 if (avail > 0) {//缓冲区不为空 if (len < avail) {//需要读取长度小于剩余长度 avail = len; } System.arraycopy(buf, pos, b, off, avail); pos += avail;//修改读取指针 off += avail;//修改数组偏移量 len -= avail;//修改剩余需读取长度 } if (len > 0) { len = super.read(b, off, len);//直接从流中读取剩余数据 if (len == -1) {//流已关闭,数据发送完毕 return avail == 0 ? -1 : avail; } return avail + len; } return avail;//返回实际读取长度 }
推回字节数据(推回到缓冲区
public void unread(int b) throws IOException { ensureOpen(); if (pos == 0) {//无法推回,缓冲区已满 throw new IOException("Push back buffer is full"); } buf[--pos] = (byte)b; }
推回字节数据(推回一个数组
public void unread(byte[] b, int off, int len) throws IOException { ensureOpen(); if (len > pos) {//缓冲区无用空间小于推回长度 throw new IOException("Push back buffer is full"); } pos -= len; System.arraycopy(b, off, buf, pos, len); }
推回数组
public void unread(byte[] b) throws IOException { unread(b, 0, b.length); }
返回可无阻塞读取的数据量
public int available() throws IOException { ensureOpen(); int n = buf.length - pos; int avail = super.available(); return n > (Integer.MAX_VALUE - avail)//返回缓冲区有效值与流中有效值的和和int最大值中较小的值 ? Integer.MAX_VALUE : n + avail; }
跳过后续的字节
public long skip(long n) throws IOException { ensureOpen(); if (n <= 0) { return 0; } long pskip = buf.length - pos;//缓冲区可跳过的数据值 if (pskip > 0) { if (n < pskip) {//可直接跳过 pskip = n; } pos += pskip;//修改缓冲区偏移量 n -= pskip;//修改剩余需跳过数据 } if (n > 0) { pskip += super.skip(n);//直接从流中跳过剩余数据 } return pskip;//返回实际需要跳过的值 }
是否支持标记回滚操作(不支持
public boolean markSupported() { return false; }
标记操作(当然为空
public synchronized void mark(int readlimit) { }
回滚操作(当然也为空
public synchronized void reset() throws IOException { throw new IOException("mark/reset not supported"); }
关闭流
public synchronized void close() throws IOException { if (in == null) return; in.close();//内嵌的输入流关闭 in = null; buf = null;//缓冲区释放 }
该类的推回操作蛮有意思的,以前并没有使用过该类,对该操作不是很熟悉。不过该操作相当于对流数据进行了分隔,对输出的数据进行了分离和加工。同时需要注意该类的缓冲区储存的并不是从流中读取出的数据,而是推回的数据,所以缓冲区的设置应该大于你想推回的最大数据值(尽量不要使用默认构造函数,请自己指定缓冲区大小)。