JDK1.8-ByteArrayInputStream类原码及分析


package java.io;

/**
 * 字节输入流
 */
public class ByteArrayInputStream extends InputStream {

    //字节数组
    protected byte buf[];

    //起始位/当前读取位置
    protected int pos;

    //标记位
    protected int mark = 0;

    //数组长度
    protected int count;

    /**
     * 构造方法 根据传入数组初始化属性信息
     * @param buf
     */
    public ByteArrayInputStream(byte buf[]) {
        this.buf = buf; //字节数组为传入数组
        this.pos = 0; //起始位为0
        this.count = buf.length; //长度为数组长度
    }

    /**
     * 构造方法
     * @param buf
     * @param offset 起始位偏移量
     * @param length 长度
     */
    public ByteArrayInputStream(byte buf[], int offset, int length) {
        this.buf = buf; //字节数组为传入数组
        this.pos = offset; //起始位为传入偏移量位置
        this.count = Math.min(offset + length, buf.length); //长度取(起始位+传入长度与数组长度)中较小的值
        this.mark = offset; //标记位为偏移量位置
    }

    /**
     * 读取一个字节
     * 为什么需要 buf[pos++] & 0xff?
     * buf[pos++] & 0xff 将pos位置的字节取出 按位与 0xff 将字节转为int类型
     * 原因是byte表示范围为-128 ~ 127 
     * 而方法定义中 -1 是流读取结束的标志,此时 结束标志-1与实际读取到的字节位-1有冲突
     * 所以将byte转为int 此时byte的-1被转为int的255 从而保证整个数据的读取完整性
     */
    public synchronized int read() {
        /**
         * pos < count 当前位 小于 数组长度
         *  是:
         *  buf[pos++] 获取pos位置的字节 并将pos值加1
         *  buf[pos++] & 0xff 将pos位置的字节转为int类型返回
         *  否:
         *  返回 -1
         * 
         */
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }

    /**
     * 按长度读取
     * @param b 待读取数组
     * @param off 读取偏移量
     * @param 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) { //起始位偏移量小于0 或读取长度小于0 或读取长度大于待读取数组长度减偏移量
            throw new IndexOutOfBoundsException(); //报错 索引越界
        }

        if (pos >= count) { //当前值大于等于数组长度时 表示已读取到结束位
            return -1; //直接返回
        }

        int avail = count - pos; //定义剩余可读取长度量 为数组长度减去起始位
        if (len > avail) { //如果读取长度大于剩余可读取长度
            len = avail; //将读取长度重置为剩余可读取长度
        }
        if (len <= 0) { //如果读取长度小于等于0 表示不读取数据
            return 0; //直接返回
        }
        /**
         * 数组拷贝
         * buf 原数组
         * pos 原数组起始位
         * b 目标数组
         * off 目标数组起始位
         * len 拷贝长度
         */
        System.arraycopy(buf, pos, b, off, len);
        pos += len; //起始位 = 原起始位 + 本次读取长度
        return len; //返回读取长度
    }

    /**
     * 跳过指定长度不读取
     * @param n 需要跳过的长度
     */
    public synchronized long skip(long n) {
        long k = count - pos; //定义中间量 值为数组长度减去起始位长度 即剩余可读取长度
        if (n < k) { //若需要跳过的长度小于剩余可读取长度时
            k = n < 0 ? 0 : n; //中间量重新赋值 当需要跳过的长度小于0时 中间量为0 否则为需要跳过的长度
        }

        pos += k; //将起始位变更为 原起始位 + 需要跳过的长度
        return k; //返回需要跳过的长度值
    }

    /**
     * 返回剩余可读的字节数量
     */
    public synchronized int available() {
        return count - pos; //数组总长度 减去 当前位置
    }

    /**
     * 判断当前流是否支持标记流
     */
    public boolean markSupported() {
        return true;
    }

    /**
     * 标记读取位置,下次还可以从这里开始读取,使用前要看当前流是否支持,可以使用 markSupport() 方法判断
     */
    public void mark(int readAheadLimit) {
        mark = pos;
    }

    /**
     * 重置读取位置为上次 mark 标记的位置
     */
    public synchronized void reset() {
        pos = mark;
    }

    /**
     * 读取完,关闭流,释放资源
     */
    public void close() throws IOException {
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值