sequenceinputstream 用于按序串联多个 inputstream 成单一逻辑流,不复制数据或生成文件;需确保各流独立有效、顺序正确,推荐 jdk 9+ 改用 inputstream.concat。
sequenceinputstream 的作用不是“合并文件”,而是把多个 inputstream 变量按顺序串成一个可顺序读取的单一逻辑流。它不复制数据、不生成新文件,只控制读取次序——真正处理数据,还得靠你后续用 fileoutputstream、files.copy() 或其他方式消费这个串联后的流。
确保输入流变量有序且独立
每个 InputStream 必须对应一个真实、未关闭、可读取的资源(如 FileInputStream、ByteArrayInputStream 等),且顺序必须严格符合业务要求:
- 不能复用同一个流对象多次(例如把同一个 FileInputStream 加入两次),否则第二次读取会从上次 EOF 位置开始,结果为空或异常
- 若流来自文件,命名含序号(如 part1.dat、part2.dat),建议提取数字排序,避免字符串排序出错("part10.dat" 会排在 "part2.dat" 前)
- 内存流(如 ByteArrayInputStream)可直接创建多个实例,无需担心资源泄漏,但也要保证内容顺序正确
构造 SequenceInputStream 的两种方式选对场景
根据输入流数量和灵活性需求选择构造方式:
- 两个流:直接用 new SequenceInputStream(in1, in2) —— 简洁安全,适合硬编码固定组合
- 三个及以上流:必须用 new SequenceInputStream(Enumeration extends InputStream>) —— JDK 不接受 List 或 Stream,只能传 Enumeration
- 获取 Enumeration 推荐用 Vector
.elements() ;虽然 Vector 已过时,但它是唯一自带elements()方法且线程安全的集合,适配该 API 限制 - 不要用
Collections.enumeration(list)后再传给 SequenceInputStream:某些 JDK 版本下该枚举可能不可重入或提前耗尽,导致静默跳过后续流
读取时注意它的单向消耗特性
SequenceInputStream 是一次性、顺序推进的流,行为由其内部状态驱动:
- 每次
read()都先尝试当前子流;若返回 -1(EOF),自动调用nextStream()切换到下一个,直到全部读完才返回 -1 - 它不会主动关闭任何子流,除非你显式调用自身
close()—— 此时会逐个调用各子流的close() - 但它不保证子流异常时的安全清理:某个子流抛 IOException,整个链就中断,其余流可能未关闭,需配合 try-with-resources 手动兜底
- 不支持 mark/reset,也不可靠提供 available() 值,不适合需要回溯或预判长度的场景
写入目标或进一步处理的推荐做法
拿到串联流后,典型用途是写入文件或传递给解析器。关键在于资源管理和性能:
- 务必用 try-with-resources 包裹 SequenceInputStream 和目标输出流(如 FileOutputStream),避免句柄泄漏
- 写入大文件时,套一层 BufferedOutputStream,减少系统调用次数,提升吞吐
- 若需校验完整性,可在读取循环中累加字节数,比对所有源流总 length(File.length() 或 ByteArrayOutputStream.size())是否一致
- JDK 9+ 强烈建议改用 InputStream.concat(in1, in2, in3...):语法简洁、异常封装完善、支持 mark/reset(当所有子流都支持时),且无 Enumeration 陷阱











