PushbackInputStream
原理是在内部保存一个字节缓冲区,如果unRead一个字节,就会向这个缓冲区倒着写入数据,下一次read的时候,就会把该缓冲区里的字节读取出来。
当缓冲区里没数据时,跟别的字节输入流一样
但是当有数据时
例如:我们现在读取1数据,这个时候unRead 4个字节,顺序是20、21、22、23
当我们再次read的时候顺序是23、22、21、20、2
public
class PushbackInputStream extends FilterInputStream {
//回退缓冲区,默认1字节
protected byte[] buf;
//回退区中最前面一个数据的位置,回退是倒着来的buf[--pos] = X
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();
}
//最多读取len个字节数据到b[]字节数组里,起始位置off
//返回最多读到的数据
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) {
//如果回退区里的可用数据比需要的len还多
//直接avail = len
avail = len;
}
System.arraycopy(buf, pos, b, off, avail);
pos += avail;
off += avail;
len -= avail;
}
//如果回退区里的可用数据比需要的len还少,例如回退区里有5个字节可用,现在len是20,
//那么现在len == 15;就是说还要在数据流里最多再读取15个字节(注意“最多”)
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)
? Integer.MAX_VALUE
: n + avail;
}
//跳过最多n个字节,如果回退区中有数据,把回退区里的数据也算上
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;
}
}
String data = "PushbackInputStream";
ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes());
PushbackInputStream inputStream = new PushbackInputStream(in, 4);
int d;
int count = 0;
try {
while ((d = inputStream.read())!=-1) {
count++;
if(count == 5){
inputStream.unread("push".getBytes());
}
System.out.print((char)d);
}
} catch (IOException e) {
e.printStackTrace();
}
输出结果:PushbpushackInputStream