当前位置: 首页 > news >正文

SequenceInputStream的源码和Vector.class的一些函数说明(windows操作系统,JDK8)

、SequenceInputStream源码——可以顺序读取多个输入Stream的装饰器类

SequenceInputStream.class 的UML关系图,如下所示:

SequenceInputStream.class的源码,如下所示:

package java.io; import java.io.InputStream; import java.util.Enumeration; import java.util.Vector; public class SequenceInputStream extends InputStream { //顺序(序列化)装载多个被装饰输入Stream的集合,一般是Vector实例 Enumeration<? extends InputStream> e; InputStream in;//顺序(序列化)装载多个被装饰输入Stream的集合中当前正在被SequenceInputStream 对象使用的被装饰的输入Stream //构造函数,传入一个顺序(序列化)装载多个被装饰输入Stream的集合 public SequenceInputStream(Enumeration<? extends InputStream> e) { this.e = e; try { nextStream(); } catch (IOException ex) { // This should never happen throw new Error("panic"); } } //构造函数,可以将2个被装饰的输入Stream放入到集合中 public SequenceInputStream(InputStream s1, InputStream s2) { Vector<InputStream> v = new Vector<>(2); v.addElement(s1); v.addElement(s2); e = v.elements(); try { nextStream(); } catch (IOException ex) { // This should never happen throw new Error("panic"); } } //获取集合中下一个被装饰的输入Stream final void nextStream() throws IOException { if (in != null) { in.close();//先关闭当前被装饰的输入Stream } if (e.hasMoreElements()) {//如果集合中还有被装饰的输入Stream in = (InputStream) e.nextElement();//获取集合中下一个被装饰的输入Stream if (in == null) throw new NullPointerException();//如果集合中下一个被装饰的输入Stream为null,抛出一个NullPointerException } else in = null;//如果集合中没有了被装饰的输入Stream,将当前正在使用的被装饰的输入Stream置为null } //判断当前正在使用的被装饰的输入Stream是否还有可以读取的字节数据 public int available() throws IOException { if (in == null) { return 0; // no way to signal EOF from available() } return in.available(); } //从SequenceInputStream 对象的集合(该集合放着多个被装饰的输入Stream)中读取1个字节 public int read() throws IOException { while (in != null) {//如果in!=null,则说明当前这个SequenceInputStream 对象的集合中还有被装饰的输入Stream没有关闭 int c = in.read();//从当前正在使用的被装饰的被装饰输入Stream中读取1个字节 if (c != -1) {//c != -1说明从当前正在使用的被装饰输入Stream中读取到了字节 return c;//返回读取到的这个字节 } nextStream();//如果c==-1说明当前正在使用的被装饰输入Stream中字节(byte)数据已经读完,获取SequenceInputStream 对象的集合中下一个被装饰的输入Stream } return -1;//如果SequenceInputStream 对象的集合中所有被装饰的输入Stream中的字节(byte)数据都已经读完,返回-1 } //从SequenceInputStream 对象的集合(该集合放着多个被装饰的输入Stream)中读取len个字节,放入到byte[]数组b的[off,off+len)(左闭右开,不包括off+len)索引位置 public int read(byte b[], int off, int len) throws IOException { if (in == null) {//如果in==null,则说明当前这个SequenceInputStream 对象的集合中所有被装饰的输入Stream都已经关闭 return -1; } else if (b == null) { throw new NullPointerException();//如果byte[]数组b==null,抛出一个NullPointerException } else if (off < 0 || len < 0 || len > b.length - off) {//相当于off + len > b.length(源码中这样写代码的好处我没看出来) throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0;//要从SequenceInputStream 对象的集合(该集合放着至少2个被装饰的输入Stream)中读取的len个字节==0时,返回0 } do { int n = in.read(b, off, len);//从当前正在使用的被装饰的输入Stream中读取len个字节,放入到byte[]数组b的[off,off+len)(左闭右开,不包括off+len)索引位置 if (n > 0) { return n;//只要能从当前正在使用的被装饰的输入Stream中读取到字节,则返回读取的数量 } nextStream();//此时n==-1,说明当前正在使用的被装饰的输入Stream中字节(byte)数据已经读完,获取SequenceInputStream 对象的集合中下一个被装饰的输入Stream } while (in != null);//SequenceInputStream 对象的集合中下一个被装饰的输入Stream为null时,跳出循环,返回-1 return -1; } //顺序关闭SequenceInputStream 对象的集合中所有被装饰的输入Stream public void close() throws IOException { do { nextStream(); } while (in != null); } }
1.1、SequenceInputStream的read()函数和nextStream()函数
package java.io; import java.io.InputStream; import java.util.Enumeration; import java.util.Vector; public class SequenceInputStream extends InputStream { ...省略部分代码... //顺序(序列化)存储多个被装饰的输入Stream的集合,一般是Vector实例 Enumeration<? extends InputStream> e; InputStream in;//顺序(序列化)装载多个被装饰输入Stream的集合中当前正在被SequenceInputStream 对象使用的被装饰的输入Stream //获取集合中下一个被装饰的输入Stream final void nextStream() throws IOException { if (in != null) { in.close();//先关闭当前被装饰的输入Stream } if (e.hasMoreElements()) {//如果集合中还有被装饰的输入Stream in = (InputStream) e.nextElement();//获取集合中下一个被装饰的输入Stream if (in == null) throw new NullPointerException();//如果集合中下一个被装饰的输入Stream为null,抛出一个NullPointerException } else in = null;//如果集合中没有了被装饰的输入Stream,将当前正在使用的被装饰的输入Stream置为null } //从SequenceInputStream 对象的集合(该集合放着多个被装饰的输入Stream)中读取1个字节 public int read() throws IOException { while (in != null) {//如果in!=null,则说明当前这个SequenceInputStream 对象的集合中还有被装饰的输入Stream没有关闭 int c = in.read();//从当前正在使用的被装饰的被装饰输入Stream中读取1个字节 if (c != -1) {//c != -1说明从当前正在使用的被装饰输入Stream中读取到了字节 return c;//返回读取到的这个字节 } nextStream();//如果c==-1说明当前正在使用的被装饰输入Stream中字节(byte)数据已经读完,获取SequenceInputStream 对象的集合中下一个被装饰的输入Stream } return -1;//如果SequenceInputStream 对象的集合中所有被装饰的输入Stream中的字节(byte)数据都已经读完,返回-1 } ...省略部分代码... }

如果使用者用的是2个被装饰的输入Stream(此处为FileInputStream),构造的SequenceInputStream的对象,如下所示(伪代码):

is1 = new FileInputStream("D:\\data1.txt"); is2 = new FileInputStream("D:\\data2.txt"); sequenceInputStream = new SequenceInputStream(is1, is2);

那么,SequenceInputStream对象中Vector集合的容量是2,如果此时执行SequenceInputStream.class::read()函数。

//伪代码 int readByte = -1; while ((readByte = sequenceInputStream.read()) != -1) { System.out.print((char) readByte); }

过程如下(假设2个被装饰的输入Stream(此处为FileInputStream)中的字节数据如下):

①、先执行第1个被装饰的输入Stream(也是Vector集合的第1个元素)的read()函数,直到该函数返回-1,如下所示:

②、关闭第1个被装饰的输入Stream(也是Vector集合的第1个元素),再执行第2个被装饰的输入Stream(也是Vector集合的第2个元素)的read()函数,直到该函数返回-1,如下所示:

1.1.1、使用举例

下面这个例子就恰当的使用SequenceInputStream的read()函数;

  • 我的windows操作系统的D盘根目录下有2个txt文件,一个是data1.txt,另一个是data2.txt文件,这2个文件中总共有30个字节,如下所示:

  • 使用者可以用一个SequenceInputStream对象装饰2个被装饰的输入Stream(此处为FileInputStream),如下代码所示:

package com.chelong.StreamAndReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; public class SequenceInputStreamTest { public static void main(String[] args) { InputStream is1 = null; InputStream is2 = null; SequenceInputStream sequenceInputStream = null; try { is1 = new FileInputStream("D:\\data1.txt"); is2 = new FileInputStream("D:\\data2.txt"); sequenceInputStream = new SequenceInputStream(is1, is2); int readByte = -1; while ((readByte = sequenceInputStream.read()) != -1) { System.out.print((char) readByte); } } catch (IOException e) { e.printStackTrace(); } finally { //此处省略关闭所有的Stream的代码 } } }

程序运行结果,如下所示:

1.2、SequenceInputStream的read(byte b[], int off, int len)函数和nextStream()函数
package java.io; import java.io.InputStream; import java.util.Enumeration; import java.util.Vector; public class SequenceInputStream extends InputStream { ...省略部分代码... //顺序(序列化)装载多个被装饰输入Stream的集合,一般是Vector实例 Enumeration<? extends InputStream> e; InputStream in;//顺序(序列化)装载多个被装饰输入Stream的集合中当前正在被SequenceInputStream 对象使用的被装饰的输入Stream //获取集合中下一个被装饰的输入Stream final void nextStream() throws IOException { if (in != null) { in.close();//先关闭当前被装饰的输入Stream } if (e.hasMoreElements()) {//如果集合中还有被装饰的输入Stream in = (InputStream) e.nextElement();//获取集合中下一个被装饰的输入Stream if (in == null) throw new NullPointerException();//如果集合中下一个被装饰的输入Stream为null,抛出一个NullPointerException } else in = null;//如果集合中没有了被装饰的输入Stream,将当前正在使用的被装饰的输入Stream置为null } //从SequenceInputStream 对象的集合(该集合放着多个被装饰的输入Stream)中读取len个字节,放入到byte[]数组b的[off,off+len)(左闭右开,不包括off+len)索引位置 public int read(byte b[], int off, int len) throws IOException { if (in == null) {//如果in==null,则说明当前这个SequenceInputStream 对象的集合中所有被装饰的输入Stream都已经关闭 return -1; } else if (b == null) { throw new NullPointerException();//如果byte[]数组b==null,抛出一个NullPointerException } else if (off < 0 || len < 0 || len > b.length - off) {//相当于off + len > b.length(源码中这样写代码的好处我没看出来) throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0;//要从SequenceInputStream 对象的集合(该集合放着至少2个被装饰的输入Stream)中读取的len个字节==0时,返回0 } do { int n = in.read(b, off, len);//从当前正在使用的被装饰的输入Stream中读取len个字节,放入到byte[]数组b的[off,off+len)(左闭右开,不包括off+len)索引位置 if (n > 0) { return n;//只要能从当前正在使用的被装饰的输入Stream中读取到字节,则返回读取的数量 } nextStream();//此时n==-1,说明当前正在使用的被装饰的输入Stream中字节(byte)数据已经读完,获取SequenceInputStream 对象的集合中下一个被装饰的输入Stream } while (in != null);//SequenceInputStream 对象的集合中下一个被装饰的输入Stream为null时,跳出循环,返回-1 return -1; } ...省略部分代码... }

如果使用者用的是2个被装饰的输入Stream(此处为FileInputStream),构造的SequenceInputStream的对象,如下所示(伪代码):

is1 = new FileInputStream("D:\\data1.txt"); is2 = new FileInputStream("D:\\data2.txt"); sequenceInputStream = new SequenceInputStream(is1, is2);

那么,SequenceInputStream对象中Vector集合的容量是2,并且假设这2个被装饰的输入Stream(此处为FileInputStream)中的字节数据如下:

如果此时执行SequenceInputStream.class::read()函数。接下来使用SequenceInputStream对象读取字节数据到使用者创建的byte[]数组,如果使用者创建的字节数组byte[]的长度>=第1个被装饰的输入Stream中的所有字节个数,比如,使用者创建的byte[]数组的长度为12,如下所示(伪代码):

int readByte = -1; byte[] buff = new byte[12]; while ((readByte = sequenceInputStream.read(buff, 0, buff.length)) != -1) { for (int i = 0; i < readByte; i++) { System.out.print((char) buff[i]); } }

整个执行过程如下:
①、第1次进入read()函数

②、第2次进入read()函数(重点是当前正在使用的被装饰的输入Stream中的字节数据已经读取完了时,再次读取,会返回-1,不会返回0

③、第3次进入read()函数

④、第4次进入read()函数(重点是当前正在使用的被装饰的输入Stream中的字节数据已经读取完了时,再次读取,会返回-1,不会返回0

最终使用者创建的byte[]数组中的字节(byte)数据,如下所示:

1.2.1、使用举例

下面这个例子就恰当的使用SequenceInputStream的read()函数;

  • 我的windows操作系统的D盘根目录下有2个txt文件,一个是data1.txt,另一个是data2.txt文件,这2个文件中总共有30个字节,如下所示:

  • 使用者可以用一个SequenceInputStream对象装饰2个被装饰的输入Stream(此处为FileInputStream),如下代码所示:

package com.chelong.StreamAndReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; import java.util.Vector; public class SequenceInputStreamTest { public static void main(String[] args) { InputStream is1 = null; InputStream is2 = null; SequenceInputStream sequenceInputStream = null; try { is1 = new FileInputStream("D:\\data1.txt"); is2 = new FileInputStream("D:\\data2.txt"); Vector<InputStream> vector = new Vector<InputStream>(); vector.addElement(is1); vector.addElement(is2); sequenceInputStream = new SequenceInputStream(vector.elements()); int readByte = -1; byte[] buff = new byte[12]; while ((readByte = sequenceInputStream.read(buff, 0, buff.length)) != -1) { for (int i = 0; i < readByte; i++) { System.out.print((char) buff[i]); } } System.out.println(); System.out.println("最终留在byte[]数组buff中的字节:"); for (byte b : buff) { System.out.print((char) b); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (is1 != null) is1.close(); if (is2 != null) is1.close(); if (sequenceInputStream != null) sequenceInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }

程序运行结果,如下所示:

二、Vector.class的一些函数说明

Vector 与 ArrayList 一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写 Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问 ArrayList慢。Vector的UML图,如下所示:

2.1、构造函数
函数名函数说明
public Vector()此构造函数创建的Vector中,Object[]数组的初始长度为10,capacityIncrement=0(capacityIncrement表示扩容时Object[]数组增加的长度,如果等于0的话,当Object[]数组需要扩容时,新的数组长度=2*旧数组的长度,但是新的数组长度最大为2^31-8)
public Vector(int initialCapacity)此构造函数创建的Vector中,Object[]数组的初始长度为initialCapacity,capacityIncrement=0(capacityIncrement表示扩容时Object[]数组增加的长度,如果等于0的话,当Object[]数组需要扩容时,新的数组长度=2*旧数组的长度,但是新的数组长度最大为2^31-8)
public Vector(int initialCapacity, int capacityIncrement)此构造函数创建的Vector中,Object[]数组的初始长度为initialCapacity,capacityIncrement=capacityIncrement(capacityIncrement表示扩容时Object[]数组增加的长度,如果等于0的话,当Object[]数组需要扩容时,新的数组长度=2*旧数组的长度,但是新的数组长度最大为2^31-8)
public Vector(Collection<? extends E> c)此构造函数创建的Vector中,Object[]数组的初始长度为传入集合Collection<? extends E> c的长度,capacityIncrement=0(capacityIncrement表示扩容时Object[]数组增加的长度,如果等于0的话,当Object[]数组需要扩容时,新的数组长度=2*旧数组的长度,但是新的数组长度最大为2^31-8)

2.2、常用函数

函数名函数说明
boolean add(E o)此函数将指定的元素追加到此Vector的末尾,该函数与addElement()函数的区别是,该()函数是List.interface接口规定的函数,addElement()函数是Vector自己实现的(接口中没有规定addElement()函数)
void add(int index, E element)此函数将指定的元素插入此Vector中的指定索引位置
boolean addAll(Collection<? extends E> c)此函数将指定Collection中的所有元素追加到此Vector的末尾
boolean addAll(int index, Collection<? extends E> c)此函数将指定Collection中的所有元素插入到此Vector中的指定索引位置
void addElement(E obj)此函数将指定的元素追加到此Vector的末尾,这个函数与add()函数的区别是,add()函数是List.interface接口规定的函数,这个函数是Vector自己实现的(接口中没有规定该函数)
int capacity()此函数返回此Vector的当前容量
void clear()此函数从此Vector中删除所有元素
Object clone()此函数返回此Vector的克隆对象
boolean contains(Object elem)如果此Vector包含指定的元素,则此函数返回true
boolean containsAll(Collection<?> c)如果此Vector包含指定Collection中的所有元素,则此函数返回true
void copyInto(Object[] anArray)此方法将此向量的组件复制到指定的数组中
E elementAt(int index)此函数返回Vector指定索引处的元素
Enumeration elements()此函数返回此Vector中所包含的所有元素的枚举。
void ensureCapacity(int minCapacity)此函数可增加此Vector的容量,以确保它至少可以保存最小容量元素个数
boolean equals(Object o)此函数将指定的Object与此Vector进行比较以获得相等性
E firstElement()返回此Vector的第一个元素(位于Object[]数组索引 0 处的元素)
E get(int index)返回Vector中指定索引位置的元素
int indexOf(Object elem)搜索给定参数的第一个匹配项,使用 equals ()函数测试相等性
int indexOf(Object elem, int index)搜索给定参数的第一个匹配项,从 index 处开始搜索,并使用 equals()函数测试其相等性
void insertElementAt(E obj, int index)将指定对象作为此Vector中的元素插入到指定的 索引位置
boolean isEmpty()测试此Vector中的是否不包含任何元素
E lastElement()返回此Vector的最后一个元素(位于Object[]数组索引 Object[].length-1 处的元素)
int lastIndexOf(Object elem)返回指定的对象在此Vector中最后一个匹配项的索引
int lastIndexOf(Object elem, int index)从指定的索引处开始向后搜索指定的对象,并返回搜索到的最后一个索引
E remove(int index)移除此Vector中指定索引位置的元素
boolean remove(Object o)移除此Vector中指定元素的第一个匹配项,如果此Vector不包含该元素,则所有元素保持不变,并返回false
boolean removeAll(Collection<?> c)从此Vector中移除包含在指定 Collection 中的所有元素
void removeAllElements()从此Vector中移除全部元素,并设置elementCount=0(该变量表示此Vector对象中有效元素的数量),Object[]数组的长度不变。
void removeElementAt(int index)删除指定索引处的元素
protected void removeRange(int fromIndex, int toIndex)从此 Vector 中移除索引位于 [fromIndex, toIndex)(左闭右开)之间的所有元素
boolean retainAll(Collection<?> c)如果此Vector中包含指定 Collection 中的所有元素,此函数返回true
E set(int index, E element)用指定的元素替换此Vector中指定索引处的元素
void setElementAt(E obj, int index)将此Vector指定 索引处的元素设置为指定的另一个元素
void setSize(int newSize)设置此Vector的大小
int size()返回此Vector中的元素数
List subList(int fromIndex, int toIndex)返回此 Vector的子集,该子集的元素范围为 [fromIndex, toIndex)(左闭右开)索引位置的所有元素
Object[] toArray()返回一个Object[]数组,包含此Vector中以正确顺序存放的所有元素
String toString()返回此Vector的字符串表示形式,其中包含每个元素的 String 表示形式
http://www.jsqmd.com/news/556004/

相关文章:

  • Java开发者必看:Lingbot深度模型服务端集成与高并发处理
  • 在职零基础备考西药执业药师,我的题库选择心路历程 - 医考机构品牌测评专家
  • Qwen3-0.6B-FP8企业实操:HR部门用其批量生成岗位JD与面试题
  • 检索模型bi-encoder笔记
  • 保姆级教程:手把手教你用LoRA微调通义千问3.5-2B模型,代码即用,小白也能轻松入门!
  • 文脉定序系统一键部署教程:基于Ubuntu 20.04的快速环境搭建
  • GemPy:重新定义三维地质建模的数学引擎与行业变革
  • OpenVoice语音合成技术全解析:从痛点突破到多场景落地实践
  • 如何零代码搭建专业Web直播系统?Jessibuca完全指南
  • 中药执业药师四科老师实力排名榜(2026版) - 医考机构品牌测评专家
  • 大模型训练崩了怎么办?Python调试3步定位法:从CUDA错误到梯度爆炸一网打尽
  • 2步实现格式自由:Save Image as Type让网页图片转换体验升级10倍
  • Firedrake实战指南:如何用有限元方法高效求解复杂偏微分方程
  • 用友U8 API开发实战:手把手教你使用API资源管理器完成单据操作
  • AMD ROCm开发实战指南:从环境搭建到异构计算应用
  • 从UDS协议到CANoe实操:深入理解诊断负响应码(NRC)的优先级设计逻辑
  • 备考2026执业药师考试机构选择指南_零基础、在职、二战考生速看 - 医考机构品牌测评专家
  • 开源可部署!mPLUG-Owl3-2B多模态交互工具镜像免配置快速上手指南
  • 二叉树 / 满二叉树 / 完全二叉树 / 二叉查找树
  • 数据库中的“哈希函数与布隆过滤器”
  • SEO优化软件在移动端网站优化中的应用有哪些
  • PyTorch 2.5镜像使用指南:从环境搭建到模型训练完整流程
  • 轻松掌握jq:命令行JSON处理的终极解决方案
  • Phi-3 Forest Laboratory处理复杂指令效果展示:多步骤规划与任务分解
  • 差分隐私不是调参游戏,是数学防线!Python配置必须掌握的7个拉普拉斯/高斯噪声关键参数,否则数据已裸奔
  • 大模型入门必看:从零到精通_大模型零基础教程(非常详细)
  • 2026 年 GEO 服务商综合技术实力深度测评:五家机构实战能力全景对比
  • 不止是地图:拆解天地图图层代码,看懂国产地理信息服务的命名逻辑
  • 别再乱选了!给PLC选模拟量传感器,0-10V、4-20mA、1-5V到底用哪个?
  • Windows系统依赖难题的终极解法:VisualCppRedist AIO一站式运行库管理方案