JAVA IO源码学习系列之ByteArrayInputStream

来源:互联网 发布:ms8.0 linux安装教程 编辑:程序博客网 时间:2024/05/22 01:54

简介

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! */
阅读全文
1 0
原创粉丝点击