功能简介
PushBackInputStream是针对于输入的一种扩展功能
装饰器模式中的具体的装饰类,抽象的装饰器为FilterInputStream
PushBackInputStream的重点在于理解缓冲区的使用手段
流自己不支持回退功能,想要可以pushBack 显然必须可以缓存数据 PushBackInputStream内部维护了一个字节数组 |
|
不要想固然的认为,相似BufferedInputStream,内部缓冲了一个数组,全部的数据都要通过这个缓冲区,而后对他作处理
他内部维护的缓冲区,仅仅保存pushBack的字节
|
还须要注意的是他的内部缓冲区是从后往前写入的,也就是下图中的,从右往左 下标索引大的先写入
一旦写满, 会抛出异常 throw new IOException("Push back buffer is full");
|
|
 推回一个字节 因为是从最后开始,一旦pos等于0也就是到了最前面,就无处可放了 因此抛出异常 不然,就在前面写入一个 |
 推回 指定字节数组b 从off偏移量开始的len个字节 推回len个长度,既然是从后往前设置数据,那么pos的值就是可用 空间 的个数 若是空间不够,抛出异常 不然,pos直接向前移动到指定位置 而后借助于System.arraycopy 将b 便宜量off开始拷贝到 |
 是unread(byte[] b, int off, int len)的简化形式 用于拷贝整个数组 |
从unread能够清晰的看出来 内部的缓冲区,只是为了给被回退掉的数据使用的 每次回退就是在最前面(下表索引较小的位置) 写入数据 |
read
只要明确了unread以及内部缓冲区的存放形式便可很清楚的知道read的工做方式了 |
 既然是从最后开始往前依次存放,初始时 pos == buf.length 那么但凡是有数据,pos必然,小于buf.length 也就是说,读取一个字节时,若是回退缓冲内有数据,直接返回一个字节 不然,调用父类的read方法,而父类FilterInputStream 只是简单的 封装转发请求 实际上就是直接使用内部的InputStream进行处理
|
多参数的read方法,将数据写入到指定的字节数组b中
回退缓冲区中有效字节个数为avail = buf.length - pos; 若是缓冲区中有数据,那么将首先从回退缓冲区中读取数据
若是读取的字节数少于 len 个字节,那么它将从底层输入流中读取字节
|
PushBackInputStream 不支持标记点相关的操做 |
|
总结
PushBackInputStream的实现逻辑比较清晰
我内部有一个缓冲区,你要是回退了我就往里面写入数据
每次的数据读取都是先看看缓冲区里面有没有数据,有的话就先读取回退缓冲区的
不然,就再去使用实际的流去进行读取
看得出来,若是你历来未曾回退过,那么好像什么都同样,仍是使用原来的InputStream 进行读取