摘要:简介字节数组输入流上一篇简单的介绍了一下字节输入流的超类,只提及了一下超类中定义的一些方法字节数组输入流是超类的一个具体的实现主要的操作实际上就是读取操作一个字节数组,类中定义了一个缓冲的字节数组,具体的操作通过定义一下标志位,操作次数等进
简介 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 positioncounts){ 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! */
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/68008.html
摘要:主要实现是通过改变属性的值来实现的这两个方法是对数据做标记,然后通过方法重置,主要为了方便重复读取流的数据以上就是的核心实现,其实可以看到关键的方法都是的,说明流都是阻塞的。 分析开始 ByteArrayInputStream一共有四个属性 protected byte buf[];//存放数据 protected int pos;//读取数据的偏移量 prot...
摘要:我的是忙碌的一年,从年初备战实习春招,年三十都在死磕源码,三月份经历了阿里五次面试,四月顺利收到实习。因为我心理很清楚,我的目标是阿里。所以在收到阿里之后的那晚,我重新规划了接下来的学习计划,将我的短期目标更新成拿下阿里转正。 我的2017是忙碌的一年,从年初备战实习春招,年三十都在死磕JDK源码,三月份经历了阿里五次面试,四月顺利收到实习offer。然后五月怀着忐忑的心情开始了蚂蚁金...
摘要:此类中的方法在关闭此流后仍可被调用,而不会产生任何。主要的功能是从缓冲区读取字节构造函数创建一个,使用作为其缓冲区数组。缓冲区会随着数据的不断写入而自动增长。 内存操作流 之前的所有的流操作都是针对文件的,但是有时候只是想要实现数据间转换,此时如果我们想要创建一个文件然后再删除文件,那样显得有点麻烦,因此此时的内存操作流就显得很适合这类的操作,因为它只是在内存中存储,并不会真正的创建文...
摘要:该篇主要以代码示例为主,因为上不去,看不到这个官方文档和。因为接下来的底层默认使用的就是。和功能是一致的。区别是不会抛出异常,而会抛出异常。而解析输入的文本内容依据默认的解析文本的模式。 Json-smart 该篇主要以代码示例为主,因为google上不去,看不到Json-smart这个官方文档和API。故只例举一些代码示例。因为接下来的Json-path底层默认使用的就是JsonSm...
阅读 1990·2021-09-22 16:05
阅读 9252·2021-09-22 15:03
阅读 2879·2019-08-30 15:53
阅读 1697·2019-08-29 11:15
阅读 902·2019-08-26 13:52
阅读 2347·2019-08-26 11:32
阅读 1797·2019-08-26 10:38
阅读 2561·2019-08-23 17:19