摘要:主要实现是通过改变属性的值来实现的这两个方法是对数据做标记,然后通过方法重置,主要为了方便重复读取流的数据以上就是的核心实现,其实可以看到关键的方法都是的,说明流都是阻塞的。
分析开始
ByteArrayInputStream一共有四个属性
protected byte buf[];//存放数据 protected int pos;//读取数据的偏移量 protected int mark = 0;//对读取数据做一个标记 protected int count;//count=buf.length 数据量的大小
read()方法主要是先判断数据是否读完,如果读完则返回-1(所以数据读完了我们会经常用read()==-1来判断),如果没有读完则读取pos的数据然后将pos加1,那么下次则读取的数据是pos则是1,接着是一个 & 0xff的操作,这个其实是将byte数据转换成int数据,是通过位运算高位补0,例如byte的值是5,那么byte的二进制是0000 0101,那么& 0xff的操作是 0000 0101 & 1111 1111 1111 1111 1111 1111 1111 1111 = 0000 0000 0000 0000 0000 0000 0000 0101,结果没变只不过是把byte类型转换成int类型了。说明下java里,一个byte是占1个字节(8位),一个int是4个字节(32位)
public synchronized int read() { return (pos < count) ? (buf[pos++] & 0xff) : -1; }
还有read()的方法,这个方法主要是将数据读到第一个参数的byte[]里去,与上面read()的差别是这个是有点像是一下读去一块数据,所以效率会比上面一个块,第二的参数off是从哪个位置开始读,len是读取的需要读取的长度是多少,读完后会将pos的位置加上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) { //装数据byte[]的长度一定要小于,读取的长度-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);//拷贝数据到byte[]块里 pos += len;//设置读取的偏移量 return len; }
skip()这个方法是跳过不需要读取的数据,然后直接读取想要的数据。主要实现是通过改变属性pos的值来实现的
public synchronized long skip(long n) { long k = count - pos; if (n < k) { k = n < 0 ? 0 : n; } pos += k; return k; }
mark(),rest()这两个方法是mark()对数据做标记,然后通过reset()方法重置,主要为了方便重复读取流的数据
public void mark(int readAheadLimit) { mark = pos; } public synchronized void reset() { pos = mark; }
以上就是ByteArrayInputStream的核心实现,其实可以看到关键的方法都是synchronized的,说明io流都是阻塞的。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/68820.html
摘要:简介字节数组输入流上一篇简单的介绍了一下字节输入流的超类,只提及了一下超类中定义的一些方法字节数组输入流是超类的一个具体的实现主要的操作实际上就是读取操作一个字节数组,类中定义了一个缓冲的字节数组,具体的操作通过定义一下标志位,操作次数等进 简介 ByteArrayInputStream 字节数组输入流 上一篇简单的介绍了一下字节输入流的超类,只提及了一下超类中定义的一些方法;字节数组...
摘要:类图结构如上,主要流程如下类实现接口类中和接口。对于,通过定义对象并调用方法对进行反序列化。底层还是通过调用的操作和类实现的序列化和反序列化。 showImg(https://segmentfault.com/img/bVJxmP?w=938&h=672); redis在缓存POJO的时候需要将POJO序列化为byte数组进行存储,spring-data-redis实现了类JdkSer...
摘要:类图结构如上,主要流程如下类实现接口类中和接口。对于,通过定义对象并调用方法对进行反序列化。底层还是通过调用的操作和类实现的序列化和反序列化。 showImg(https://segmentfault.com/img/bVJxmP?w=938&h=672); redis在缓存POJO的时候需要将POJO序列化为byte数组进行存储,spring-data-redis实现了类JdkSer...
摘要:类图结构如上,主要流程如下类实现接口类中和接口。对于,通过定义对象并调用方法对进行反序列化。底层还是通过调用的操作和类实现的序列化和反序列化。 showImg(https://segmentfault.com/img/bVJxmP?w=938&h=672); redis在缓存POJO的时候需要将POJO序列化为byte数组进行存储,spring-data-redis实现了类JdkSer...
阅读 939·2021-09-27 13:36
阅读 885·2021-09-08 09:35
阅读 1063·2021-08-12 13:25
阅读 1436·2019-08-29 16:52
阅读 2906·2019-08-29 15:12
阅读 2725·2019-08-29 14:17
阅读 2605·2019-08-26 13:57
阅读 1011·2019-08-26 13:51