1

分析开始

  • 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流都是阻塞的。


review
9 声望0 粉丝