JAVA IO源码学习系列一(ByteArrayInputStream)

简介

ByteArrayInputStream 字节数组输入流

上一篇简单的介绍了一下字节输入流的超类,只提及了一下超类中定义的一些方法;字节数组输入流是超类的一个具体的实现:主要的操作实际上就是读取操作一个字节数组,类中定义了一个缓冲的字节数组,具体的操作通过定义一下标志位,操作次数等进行读取该字节数组中的内容;


1.主要方法源码介绍

1.介绍过程依据第一篇中的描述的过程;
(1)首先介绍类中的属性内容:

//存放字节流数组,实际的操作的数据内容
protected byte buf[];
//当前读取的位置,在相关操作中会修改这个读取位置
protected int pos;
//标记读取的位置,如果有需要标记,可以使用mark()方法标记位置
protected int mark = 0;
//字节流数组大小
protected int count;

(2)然后是定义构造字节数组内容:该类提供了两种方式的构造函数;第一种直接指定字节数组输入流中缓冲的流数组,(这样后续的读取等操作都是在处理这个数组中的数据),该构造函数中设置了上面提到的相关属性;
第二种则指定了具体位置和大小,但实际的数据已全部在缓冲的数组中,只是确实了读取的位置和大小,所以可以读取的内容比实际的内容少;

public ByteArrayInputStream(byte buf[]) {
        this.buf = buf;
        this.pos = 0;
        this.count = buf.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;
    }

(3)判断是否还能读取:根据当前读取的位置来确定是否还有数据

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

(4)具体的读取数据:读取操作及先判断满足读取条件后读取一个缓冲数组中的数据,并将读取位置+1,&0xff的意义在于保证数据操作的一致性(计算机存储数据机制方面)

 public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }
   

读取数据到指定的字节数组中,可以指定读取的位置和大小

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();
        }

        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);
        pos += len;
        return len;
    }

(5)操作完记得关闭close();

2.其他方法简介:

1.skip()跳过,忽略:及修改读取位置

 public synchronized long skip(long n) {
        long k = count - pos;
        if (n < k) {
            k = n < 0 ? 0 : n;
        }

        pos += k;
        return k;
    }

2.mark():标记位置,操作过程中标记需要的位置,这样在后面可以通过reset()方法将读取位置修改到这个值,这样就可以再此从此位置读取数据;

 public void mark(int readAheadLimit) {
        mark = pos;
    }

3.reset():上面介绍过了,

 public synchronized void reset() {
        pos = mark;
    }

3.差不多就介绍完了,附上自己重写的代码

/**
 1. 数组字节输入流
 */
public class MyByteArrayInputStream {
    
    //存放字节流数组
    protected byte buffer[];
    
    //当前读取的位置
    protected int position;
    
    //字节流数组大小
    protected int counts;
    
    //标记读取的位置
    protected int mark;
    
    /**
     * 指定字节数组构造输入流
     * @param buf 指定数组
     */
    public MyByteArrayInputStream(byte[] buf) {
       this.buffer = buf;
       this.counts = buf.length;
    }
    
    public MyByteArrayInputStream(byte[] buf,int offset,int length) {
        this.position = offset;
        this.mark = offset;
        this.buffer = buf;
        this.counts = Math.min(buf.length, length+offset);
     }
    
    //读取字节数组中的字节流
    public synchronized int read(){
        return position<counts ? buffer[position++] :-1;
    }
    
    //将数组中的字节流读入指定字节数组
    public int read(byte[] buf,int offset,int length){
        if(buf==null){
            throw new NullPointerException("写入的数组为null");
            
        }else if((offset<0)||(length<0)||(buf.length-offset<length)){
            throw new IndexOutOfBoundsException("数组越界了");
        }
       //当前数组中的读取位置超出数组大小,则无数据可读
        if(position>counts){
            return -1;
        }
        //
        int can = counts - position;
        if(length > can){
            length = can;
        }
        
        if(length <=0){
            return 0;
        }
        System.arraycopy(buffer, position, buf, offset, length);
        position += length;
        return length;
    }

    //跳过字节数组中的n个字节
    public synchronized long skip(long n){
        //当前可读取的数量
        long can = counts-position;
        //当跳过的大小小于可读取的数量时
        if(n < can){
            //值大于0 设置跳过的次数为 n ,否则为0;
            can = n < 0 ? 0 : n;
        }
        //设置当前读取的位置,跳过n个
        position +=can;
        //返回实际跳过的值
        return can;
    }
    
    //是否支持标记,支持
    public boolean markSupported(){
        return true;
    }
    
    //标记当前读取的位置,与重置相对,标记之后,使用重置方法可以在指定位置读取
    public void mark(){
        mark = position;
    }
    //设置当前读取的位置为上一次标记的位置
    public synchronized void reset(){
        position = mark;
    }
    //剩余可以去到的数量
    public synchronized int available(){
        return  counts-position;
    }
    
    //关闭操作
    public void close() throws IOException {
    }
}

## 4. 最后召唤神兽##

/**
 *                  ___====-_  _-====___
 *            _--^^^#####//      \\#####^^^--_
 *         _-^##########// (    ) \\##########^-_
 *        -############//  |\^^/|  \\############-
 *      _/############//   (@::@)   \\############\_
 *     /#############((     \\//     ))#############\
 *    -###############\\    (oo)    //###############-
 *   -#################\\  / VV \  //#################-
 *  -###################\\/      \//###################-
 * _#/|##########/\######(   /\   )######/\##########|\#_
 * |/ |#/\#/\#/\/  \#/\##\  |  |  /##/\#/  \/\#/\#/\#| \|
 * `  |/  V  V  `   V  \#\| |  | |/#/  V   '  V  V  \|  '
 *    `   `  `      `   / | |  | | \   '      '  '   '
 *                     (  | |  | |  )
 *                    __\ | |  | | /__
 *                   (vvv(VVV)(VVV)vvv)                
 *                        神兽保佑
 *                       代码无BUG!
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值