Java中IO框架——ByteArrayInputStream源码解析

ByteArrayInputStream 继承自 InputStream 父类。
字节数组输入流在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区中。

属性

    // 由该流的创建者提供的字节数组
    protected byte buf[];
    // pos可以理解为游标,指向数组中的哪个位置
    protected int pos;
    // 流中当前的标记位置,初始为0
    protected int mark = 0;
    // buf字节数组中比最后一位存放字节位置索引大1的位置
    protected int count;

构造函数

    // 根据给定的字节数组构造一个输入流
    public ByteArrayInputStream(byte buf[]) {
        this.buf = buf;
        // 偏移量为0
        this.pos = 0;
        // count为字节数组的长度
        this.count = buf.length;
    }

    // 根据给定的字节数组,偏移量,字节总数构造一个输入流
        public ByteArrayInputStream(byte buf[], int offset, int length) {
        this.buf = buf;
        // 游标从offset位置开始
        this.pos = offset;
        // count最大也不能超出字节数组的总长度
        this.count = Math.min(offset + length, buf.length);
        // 标记位置也是从offset位置开始
        this.mark = offset;
    }

重要方法

read()

同步方法,读取字节数组buf中的下一个字节。返回值int,其实是返回的字节byte,转为int返回。

    public synchronized int read() {
        // 这里只要当前游标位置没有走完最后一个字节,即pos<count
        // 就返回pos++位置的字节,转为int返回
        // 如果游标已经走到了count位置,此位置已经没有字节可读,返回-1
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }

read(byte b[], int off, int len)

也是同步方法,读取字节数组 buf 中一定数量的字节到字节数组 b 中,并从 b 数组 off 下标开始存放。
b 是目标数组,off 是目标数组 b 中开始存放的偏移量,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) {
            throw new IndexOutOfBoundsException();
        }
        // 如果游标pos走到了count位置,已经没有字节可读,返回-1 
        if (pos >= count) {
            return -1;
        }
        // 剩余可读的字节数量avail,等于count减去当前读取位置
        // pos位置的当前还未读取,一直到最后一个有字节的下标 (count-1) 总共的个数为
        // (count-1)-pos+1 = count-pos
        int avail = count - pos;
        // 需要读取的字节数不能超过可读字节数
        if (len > avail) {
            len = avail;
        }
        // 需要读取的字节数如果不大于0,即不需要读取,那么直接返回读取的字节总数为0即可。
        if (len <= 0) {
            return 0;
        }
        // 执行数组拷贝,从buf的pos位置开始拷贝len个字节到b数组的off位置开始。
        System.arraycopy(buf, pos, b, off, len);
        // 数组复制完成后,游标pos要往后走len个长度
        pos += len;
        // 返回读取的字节总数len
        return len;
    }

skip(long n)

跳过字节数组buf中的 n 个字节。返回值为跳过的数量。

    public synchronized long skip(long n) {
        // k为当前可读的字节数量
        long k = count - pos;
        // 如果需跳过的比剩余的可读字节少
        if (n < k) {
            // 那么需跳过多少字节就可以跳过多少
            k = n < 0 ? 0 : n;
        }
        // 上边如果n>k,即需跳过的字节比剩余字节还多,那么就全跳过即可
        // 这里游标要向后移动k个位置,因为跳过了k个字节
        pos += k;
        // 返回跳过的字节总数k
        return k;
    }

available()

返回字节数组中可以读取的剩余字节总数。
(count-1) 位置是最后一个有字节的位置,
pos 位置是当前游标的位置(还未读取),
那么总数为 (count-1)-pos+1 = count-pos 。

    public synchronized int available() {
        return count - pos;
    }

mark/reset

    // 支持标记及重置位置
    public boolean markSupported() {
        return true;
    }
    // 将当前游标位置设置为标记点,此标记点可用于还原重置
    // 注意readAheadLimit无意义
    public void mark(int readAheadLimit) {
        mark = pos;
    }
    // 还原位置,将之前保存的标记为作为游标位置
    public synchronized void reset() {
        pos = mark;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值