SequenceInputStream 是 Java 中按顺序串联多个 InputStream 的工具类,支持 Enumeration 或两个流构造,不自动关闭子流,适用于一次性顺序拼接场景。

SequenceInputStream 是 Java 中用于按顺序串联多个输入流的工具类,它把多个 InputStream 当作一个逻辑上的单一输入流来读取,数据会从第一个流开始读完,再自动切换到下一个流,直到全部读尽。
基本用法:传入 Enumeration 或两个 InputStream
它有两种构造方式:
- 接收一个
Enumeration extends InputStream>,适合动态数量的流(如从集合生成) - 接收两个
InputStream(in1和in2),内部会将它们包装成一个枚举,适合固定两个流的场景
注意:传入的每个流必须是**可重复读取的**(或至少在被 SequenceInputStream 读取时保持打开且有效),否则中途可能抛出异常或跳过数据。
合并多个字节数组流的典型示例
常见需求是把几个 byte[] 的内容拼起来读。可以用 ByteArrayInputStream 包装后交给 SequenceInputStream:
立即学习“Java免费学习笔记(深入)”;
byte[] data1 = "Hello".getBytes();
byte[] data2 = " ".getBytes();
byte[] data3 = "World!".getBytes();
InputStream in1 = new ByteArrayInputStream(data1);
InputStream in2 = new ByteArrayInputStream(data2);
InputStream in3 = new ByteArrayInputStream(data3);
// 构造 Enumeration(Java 8+ 可用 Collections.enumeration)
Vector<InputStream> streams = new Vector<>();
streams.add(in1);
streams.add(in2);
streams.add(in3);
SequenceInputStream seq = new SequenceInputStream(streams.elements());
// 读取全部内容
ByteArrayOutputStream out = new ByteArrayOutputStream();
int b;
while ((b = seq.read()) != -1) {
out.write(b);
}
System.out.println(out.toString()); // 输出:Hello World!
使用 try-with-resources 的注意事项
SequenceInputStream 本身实现了 AutoCloseable,但它**不会自动关闭内部的各个子流**(这是设计使然)。如果需要确保所有底层流都被关闭,需手动管理或封装:
- 推荐做法:用 try-with-resources 分别包裹每个子流,并在 finally 或辅助方法中统一关闭
- 也可以自定义一个继承
SequenceInputStream的类,在close()中遍历并关闭所有子流(需保存引用) - 若子流来自文件或网络,忽略关闭会导致资源泄漏
适用场景与限制
适合一次性顺序拼接、无需随机访问的场景,比如:
- 合并多个配置片段(如 classpath 下多个 properties 文件)
- 构造测试用的复合输入(模拟分段传输)
- 日志聚合、消息体拼接等简单流式组装
不适用于:
- 需要并发读取或跳转位置(它不支持
mark()/reset()或skip()跨流生效) - 流数量极大且内存敏感(因为要持有所有流的引用,且不能提前释放已读完的流)
- 要求高吞吐或异步处理(它本质是同步阻塞的串行读取)


















