分析开始
- ByteArrayInputStream一共有四个属性
protected byte buf[];//存放数据
protected int pos;//读取数据的偏移量
protected int mark = 0;//对读取数据做一个标记
protected int count;//count=buf.length 数据量的大小
- read()方法主要是先判断数据是否读完,如果读完则返回-1(所以数据读完了我们会经常用read()==-1来判断),如果没有读完则读取pos的数据然后将pos加1,那么下次则读取的数据是pos则是1,接着是一个 & 0xff的操作,这个其实是将byte数据转换成int数据,是通过位运算高位补0,例如byte的值是5,那么byte的二进制是0000 0101,那么& 0xff的操作是 0000 0101 & 1111 1111 1111 1111 1111 1111 1111 1111 = 0000 0000 0000 0000 0000 0000 0000 0101,结果没变只不过是把byte类型转换成int类型了。说明下java里,一个byte是占1个字节(8位),一个int是4个字节(32位)
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
- 还有read()的方法,这个方法主要是将数据读到第一个参数的byte[]里去,与上面read()的差别是这个是有点像是一下读去一块数据,所以效率会比上面一个块,第二的参数off是从哪个位置开始读,len是读取的需要读取的长度是多少,读完后会将pos的位置加上len的数值算出数据的读取的偏移的位置
public synchronized int read(byte b[], int off, int len) {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
//装数据byte[]的长度一定要小于,读取的长度-off的长度,否则就装不下啦
throw new IndexOutOfBoundsException();
}
if (pos >= count) {
return -1;
}
int avail = count - pos;//计算剩余的有效数据
if (len > avail) {
len = avail;
}
if (len <= 0) {
return 0;
}
System.arraycopy(buf, pos, b, off, len);//拷贝数据到byte[]块里
pos += len;//设置读取的偏移量
return len;
}
- skip()这个方法是跳过不需要读取的数据,然后直接读取想要的数据。主要实现是通过改变属性pos的值来实现的
public synchronized long skip(long n) {
long k = count - pos;
if (n < k) {
k = n < 0 ? 0 : n;
}
pos += k;
return k;
}
- mark(),rest()这两个方法是mark()对数据做标记,然后通过reset()方法重置,主要为了方便重复读取流的数据
public void mark(int readAheadLimit) {
mark = pos;
}
public synchronized void reset() {
pos = mark;
}
以上就是ByteArrayInputStream的核心实现,其实可以看到关键的方法都是synchronized的,说明io流都是阻塞的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。