程序员潇然 发表于 2022-8-26 11:17:45

JavaIO之PushBackInputStream (十四)

### 功能简介

PushBackInputStream是针对于输入的一种扩展功能
装饰器模式中的具体的装饰类,抽象的装饰器为FilterInputStream
PushBackInputStream的重点在于理解缓冲区的使用手段

!(data/attachment/forum/202208/26/110900pdkg93kd0roo349a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

流本身不支持回退功能,想要能够pushBack 显然必须能够缓存数据
PushBackInputStream内部维护了一个字节数组

!(data/attachment/forum/202208/26/110921fiuqmwwmhh3cmhom.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

不要想当然的认为,类似BufferedInputStream,内部缓冲了一个数组,所有的数据都要经过这个缓冲区,然后对他做处理
他内部维护的缓冲区,仅仅保存pushBack的字节

还需要注意的是他的内部缓冲区是从后往前写入的,也就是下图中的,从右往左
下标索引大的先写入

一旦写满, 会抛出异常
`throw new IOException("Push back buffer is full");`

!(data/attachment/forum/202208/26/111005myju1630lhj104cz.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

!(data/attachment/forum/202208/26/111014mpsyas63sq0ziquc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

推回一个字节
由于是从最后开始.,一旦pos等于0也就是到了最前面,就无处可放了
所以抛出异常
否则,就在前面写入一个

本文作者:程序员潇然 疯狂的字节X https://crazybytex.com/

!(data/attachment/forum/202208/26/111039xe1ji9av33kz0kia.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

推回 指定字节数组b 从off偏移量开始的len个字节
推回len个长度,既然是从后往前设置数据,那么pos的值就是可用 空间 的个数
如果空间不够,抛出异常
否则,pos直接向前移动到指定位置
然后借助于System.arraycopy 将b 偏移量off开始拷贝到

!(data/attachment/forum/202208/26/111724ix6wyccag1yji5sl.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

是unread(byte[] b, int off, int len)的简化形式
用于拷贝整个数组

从unread可以清晰的看出来
内部的缓冲区,只是为了给被回退掉的数据使用的
每次回退就是在最前面(下表索引较小的位置)写入数据

#### read

只要明确了unread以及内部缓冲区的存放形式即可很清楚的知道read的工作方式了

!(data/attachment/forum/202208/26/112348aryyzuyitniirudv.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

既然是从最后开始往前依次存放,初始时 pos == buf.length那么但凡有数据,pos必然,小于buf.length
也就是说,读取一个字节时,如果回退缓冲内有数据,直接返回一个字节
否则,调用父类的read方法,而父类FilterInputStream 只是简单的 封装转发请求
实际上就是直接使用内部的InputStream进行处理

多参数的read方法,将数据写入到指定的字节数组b中

回退缓冲区中有效字节个数为avail = buf.length - pos;
如果缓冲区中有数据,那么将首先从回退缓冲区中读取数据

如果读取的字节数少于 len 个字节,那么它将从底层输入流中读取字节

!(data/attachment/forum/202208/26/112427g9ffjgh777yvhzbh.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

PushBackInputStream 不支持标记点相关的操作

!(data/attachment/forum/202208/26/112439y0rk1yl1fbrfyrki.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")



### 总结

PushBackInputStream的实现逻辑比较清晰

我内部有一个缓冲区,你要是回退了我就往里面写入数据

每次的数据读取都是先看看缓冲区里面有没有数据,有的话就先读取回退缓冲区的

否则,就再去使用实际的流去进行读取

看得出来,如果你从来不曾回退过,那么好像什么都一样,还是使用原来的InputStream 进行读取

!(data/attachment/forum/202206/16/141330jha7st9soow8772i.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "common_log.png")
`转载务必注明出处:程序员潇然,疯狂的字节X,https://crazybytex.com/thread-150-1-1.html `
页: [1]
查看完整版本: JavaIO之PushBackInputStream (十四)