本篇讲的java io中的SequenceInputStream流。
SequenceInputStream是一个合并流,当我们从多个流中读取数据,并希望他们合并成一个流作为数据源时,我们就可以使用SequenceInputStream。它的内部是通过Vector来实现的,至于Vector是什么会在其他的篇幅中提到,这里暂且就把它看做一个普通的集合。
下面先贴上SequenceInputStream的源码:
package java.io;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Vector;
public class SequenceInputStream extends InputStream {
//Enumeration是一个枚举接口,这里声明了一个该类型的变量
Enumeration extends InputStream> e;
//封装了一个InputStream in
InputStream in;
/**
*带有一个参数的构造方法,传入一个Enumeration的对象。
*/
public SequenceInputStream(Enumeration extends InputStream> e) {
//将传入的参数赋值给本地的e。
this.e = e;
try {
//执行nextStream方法,如果本地Enumeration对象中包含InputStream流,则将其中的第一个流赋值给本地声明的InputStream对象in。
nextStream();
} catch (IOException ex) {
// This should never happen
throw new Error("panic");
}
}
/**
*带两个参数的构造方法,两个参数都为InputStream流对象
*/
public SequenceInputStream(InputStream s1, InputStream s2) {
//定义了一个Vector对象,容量为2
Vector v = new Vector<>(2);
//将传入的两个参数传入Vector中。
v.addElement(s1);
v.addElement(s2);
//通过Vector的elements方法获得Enumeration对象,并赋值给本地声明的Enumeration对象e。
e = v.elements();
try {
//执行nextStream方法,如果本地Enumeration对象中包含InputStream流,则将其中的第一个流赋值给本地声明的InputStream对象in。
nextStream();
} catch (IOException ex) {
/ // This should never happen
throw new Error("panic");
}
}
/**
*给方法用于为本地声明的InputStream对象in赋值
*/
final void nextStream() throws IOException {
//如果in已经被创建过,那么先断开连接
if (in != null) {
in.close();
}
//遍历本地的Enumercation对象,如果其中含有元素,将其中的元素赋值给本地的InputStream对象in,每一赋值是赋值的e中的下一个元素,从
//第一个元素开始(下标为0)。
if (e.hasMoreElements()) {
in = (InputStream) e.nextElement();
if (in == null)
throw new NullPointerException();
}
//如果Enumercation对象中没有元素,则将本地InputStream对象in置为null
else in = null;
}
/**
*该方法用来判断流是否可读
*/
public int available() throws IOException {
if(in == null) {
return 0; // no way to signal EOF from available()
}
return in.available();
}
/**
*读取方法,按照字节读取,当当前流对象中读取完毕时,调用nextStream方法,换取下一个流继续进行数据读取,其中用了一次迭代方法。
*/
public int read() throws IOException {
if (in == null) {
return -1;
}
int c = in.read();
if (c == -1) {
nextStream();
return read();
}
return c;
}
/**
*读取方法,按照传入的字节数组进行读取,当当前流对象中读取完毕时,调用nextStream方法,换取下一个流继续进行数据读取,其中用了一次迭
*代方法。
*/
public int read(byte b[], int off, int len) throws IOException {
if (in == null) {
return -1;
} else if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int n = in.read(b, off, len);
if (n <= 0) {
nextStream();
return read(b, off, len);
}
return n;
}
/**
*关闭所有的流对象
*/
public void close() throws IOException {
do {
nextStream();
} while (in != null);
}
}
下面将举一个小例子来说明SequenceInputStream的使用方式:
package sequenceIO;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
public class SequenceIOTest {
public static void main(String[] args) {
String str = "Hello World!";
String str1 = "i am LiLei, how r u ,bro?";
int len;
StringBuffer message = new StringBuffer();
InputStream is1 = new ByteArrayInputStream(str.getBytes());
InputStream is2 = new ByteArrayInputStream(str1.getBytes());
SequenceInputStream sis = new SequenceInputStream(is1, is2);
try {
while((len = sis.read()) != -1){
message.append((char)len);
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(sis!=null){
sis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(message);
}
}
执行上述代码可以在控制台看到如下打印:
由此可以看出,SequenceInputStream成功将两个流中的数据汇聚到了一起,以上为本篇内容。