BufferedInputStream 是一个带有缓冲区的输入流。缓冲区你可以理解为缓存,就像我们从数据库中读数据和从缓存中读数据同样的道理,目的都是为了能够加快读取速度。
本篇只关注如下图红框的部分
//默认缓冲区大小为8192个字节 即8k
private static int DEFAULT_BUFFER_SIZE = 8192;
//缓冲区最大大小 超出将报OutOfMemoryError错误
private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
//缓冲区字节数组 即我们认为的缓存组件
protected volatile byte buf[];
//初始化
public BufferedInputStream(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}
//初始化 可自定义缓冲区大小
public BufferedInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];
}
//读取数据
public synchronized int read() throws IOException {
//pos为当前缓冲区下一个读取位置 count为缓冲区数据真实长度
//当缓冲区已经没有数据
if (pos >= count) {
//将数据读取到缓冲区
fill();
if (pos >= count)
return -1;
}
//读取缓冲区数据
return getBufIfOpen()[pos++] & 0xff;
}
private void fill() throws IOException {、
//当前缓冲区数组
byte[] buffer = getBufIfOpen();
// 默认情况下 markpos =-1 (markpos为pos的一个标记 用于重读数据,通过mark方法调用)也即 此时pos恢复到起始值
if (markpos < 0)
pos = 0;
else if (pos >= buffer.length)
//如果>0 说明有数据需要重读
if (markpos > 0) {
//保留字节个数
int sz = pos - markpos;
//读取至缓冲区头部
System.arraycopy(buffer, markpos, buffer, 0, sz);
//重置pos 及markpos
pos = sz;
markpos = 0;
} else if (buffer.length >= marklimit) {
markpos = -1;
pos = 0;
} else if (buffer.length >= MAX_BUFFER_SIZE) {
throw new OutOfMemoryError("Required array size too large");
} else {
//通过 marklimit 需要扩容 一般为pos*2 这是pos为原缓冲区的大小
int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
pos * 2 : MAX_BUFFER_SIZE;
if (nsz > marklimit)
nsz = marklimit;
//创建一个新的缓冲区
byte nbuf[] = new byte[nsz];
//初始化nbuf
System.arraycopy(buffer, 0, nbuf, 0, pos);
if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
throw new IOException("Stream closed");
}
buffer = nbuf;
}
count = pos;
//从in中读取数据至缓冲区
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
if (n > 0)
count = n + pos;
}
BufferedInputStream 主要的基本都介绍了,当然 还有mark,reset等方法,其实就是用来标记和恢复用途,不多分析了。