JavaIO之BufferedInputStream BufferedOutputStream(十三)
### 功能简介BufferedInputStream 和 BufferedOutputStream一样,他们都是过滤流
装饰器模式下具体的装饰类
用来装饰InputStream以及OutputStream下的其他的具体的实现类
比如FileInputStream
!(data/attachment/forum/202208/26/110105opbyms4k3ozqbcc6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
BufferedInputStream 和 BufferedOutputStream
都是在内部借助于字节数组,来实现缓存的
### BufferedInputStream
| BufferedInputStream | 内部使用字节数组对输入流进行缓存 |
| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| protected volatile byte buf[]; | 内部的字节数组可能动态增长,动态增长是借助于创建新数组然后复制,重新指向 |
| DEFAULT_BUFFER_SIZE | 默认大小8K 8192 |
| private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; | 缓冲区最大允许大小 |
| protected int count; | 有效字节的个数 |
| protected int pos; | buf 数组中读取的下一个字符的下标索引 |
| protected int markpos = -1; | 最后一次调用 mark 方法时 pos 字段的值 |
| protected int marklimit; | 调用 mark 方法后,在后续调用 reset 方法失败之前所允许的最大提前读取量就是最多支持的个数 |
**buf[]**; 用于实际存储字节数组的值
**DEFAULT_BUFFER_SIZE** 表示默认缓冲区的大小
**MAX_BUFFER_SIZE** 表示 最大支持的缓冲区大小
这三个字段用于存储缓冲
**pos** 用于记录读取位置
**markpos / marklimit** mark功能使用
### 构造方法
说了很多遍的装饰器模式,是你还有你
他的使用,必然离不开 InputStream
而且,它内部还会维护一个 InputStream
看下构造方法,如果不指定大小,那么将会使用默认大小
如果指定了大小,只要合法,将会创建字节数组
而且会调用父类的构造方法
父类FilterInputStream中 in是protected的
!(data/attachment/forum/202208/26/110335y5uuw4u9b33lg9us.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
!(data/attachment/forum/202208/26/110347pxrumkrhz5zm5kwe.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
#### read
提供了两个版本的read
```java
public int read();
public int read(byte[] b,int off, int len);
```
多参数的read方法将会持续读取尽可能多的数据,直到:
已经读取了指定的字节数,
底层流的 read 方法返回 -1,指示文件末尾(end-of-file),或者
底层流的 available 方法返回 0,指示将阻塞后续的输入请求
**skip /available/mark/reset/markSupported** 同InputStream的协议语义
跳过指定个数
获取可用个数
做标记
回到标记点
测试是否支持mark 和reset方法
#### close
虽然并不是直接打开资源,但是它涉及到内部的InputStream,所以需要cloase
!(data/attachment/forum/202208/26/110511bfzj9jj7oy68a93c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
### BufferedOutputStream
BufferedOutputStream内部也是通过字节数组进行缓存的
count 记录有效字节数
!(data/attachment/forum/202208/26/110531oemsfamy1t5feggl.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
构造方法也可以设置,初始化大小
如果不设置,默认是8192
!(data/attachment/forum/202208/26/110549l1692360197jwaqb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
BufferedOutputStream 内部通过字节数组进行缓存
也就是数据不直接写入磁盘
而是先写入到内部缓冲区中
所以说,flush 方法是必须的,用来执行实际写入的操作
它的内部借助于flushBuffer方法
方法实现很简单,只要有有效字节,就把有效字节通过内部的out对象写入,然后count清0
清零了就可以继续从头写了
!(data/attachment/forum/202208/26/110621cq6q556azzac5ly3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
#### write
单参数write 一旦缓冲区满了
直接全部调用底层out写入
并且重头开始缓存
!(data/attachment/forum/202208/26/110645hquyu5jfku3xq0bv.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
三参数write
将数组b 从off偏移量开始,写入len长度到流中
如果len大于缓冲区长度
将所有数据写入,刷新缓冲区
并且直接调用底层out的write 也就是不缓冲了
如果len长度没有超过缓冲区大小 可是 内部缓冲区空间不足够了 刷新缓冲区
最后将参数字节数组的数据,拷贝到缓冲区
!(data/attachment/forum/202208/26/110704gi26mkc710emx7i7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
### 总结
既然是缓冲装饰器流
所以,它内部要维护一个InputStream或者OutputStream
另外,既然提供了缓冲的功能,常用的缓冲功能自然是数组的形式
对于他们两个就是字节数组
他们内部就是都维护了一个字节数组
BufferedInputStream 会将内部底层的流读取的数据,存入到他的缓冲区中,通过BufferedInputStream提供读取功能
BufferedOutputStream 会将写入的数据,存入到他的缓冲区中,在需要的时候,在借助于内部底层的流进行真正写入
缓冲的功能,减少了跟底层磁盘直接交互的io次数,所以说,自然能够提高性能
!(data/attachment/forum/202208/26/110723slxbcbjzgmjavlrt.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
!(data/attachment/forum/202206/16/141330jha7st9soow8772i.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "common_log.png")
`转载务必注明出处:程序员潇然,疯狂的字节X,https://crazybytex.com/thread-149-1-1.html `
页:
[1]