1. SequenceInputStream概述及应用场景
SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
应用场景:多个文件合并到一个文件的场景。
构造方法:
public SequenceInputStream(Enumeration<? extends InputStream> e):
通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。将按顺序读取由该枚举生成的输入流,以提供从SequenceInputStream 读取的字节。在用尽枚举中的每个输入流之后,将通过调用该流的 close() 方法将其关闭。
public SequenceInputStream(InputStream s1, InputStream s2):
住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
区别:这两种构造方法的区别是封装Enumeration对象的工作放到代码外。最终归结于为在构造函数内Enumeration类型成员变量初始化。SequenceInputStream源码分析,合并流,把多个文件写到一个文件中去。
2. SequenceInputStream源码
public class SequenceInputStream extends InputStream {
Enumeration e;
InputStream in;
public SequenceInputStream(Enumeration<? extends InputStream> e) {
this.e = e;
try {
nextStream();
} catch (IOException ex) {
throw new Error("panic");
}
}
public SequenceInputStream(InputStream s1, InputStream s2) {
Vector 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");
}
}
final void nextStream() throws IOException {
if (in != null) {
in.close();
}
if (e.hasMoreElements()) {
in = (InputStream) e.nextElement();
if (in == null)
throw new NullPointerException();
}
else in = null;
}
public int read() throws IOException {
if (in == null) {
return -1;
}
int c = in.read();
if (c == -1) {
nextStream();
return read();
}
return c;
}
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 int available() throws IOException {
if(in == null) {
return 0; // no way to signal EOF from available()
}
return in.available();
}
public void close() throws IOException {
do {
nextStream();
} while (in != null);
}
}
3. 案例:使用SequenceInputStream合并文件
需求:把a.txt,b.txt,c.txt三个文件的内容复制到Copy.txt中 。a.txt+b.txt+c.txt – Copy.txt
public class SequenceInputStreamDemo2 {
public static void main(String[] args) throws IOException {
/*SequenceInputStream(Enumeration e)
Enumeration是Vector中的一个方法的返回值类型。
Enumeration<E> elements()
* */
Vector<InputStream> v = new Vector<InputStream>();
InputStream s1 = new FileInputStream("a.txt");
InputStream s2 = new FileInputStream("b.txt");
InputStream s3 = new FileInputStream("c.txt");
v.add(s1);
v.add(s2);
v.add(s3);
Enumeration<InputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.txt"));
byte[] bys = new byte[1024];
int len = 0;
while ((len = sis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
sis.close();
}
}