SequenceInputStream 是将多个 InputStream 逻辑串联为单一顺序输入流,不创建文件或复制数据;需自行用 FileOutputStream 或 Files.copy() 写入目标文件。

SequenceInputStream 不是“合并文件”,而是把多个 InputStream 逻辑串联成一个可顺序读取的单一输入流。它本身不创建新文件、不复制数据,只控制读取顺序——真正写入目标文件,还得靠你自己用 FileOutputStream 或 Files.copy() 完成。
SequenceInputStream 的两种构造方式怎么选
两个流就用
SequenceInputStream(InputStream s1, InputStream s2):简单直接,不用封装集合,适合硬编码场景(比如固定合并header.dat+body.dat)多个流必须用
SequenceInputStream(Enumeration extends InputStream> e):因为构造器不接受List或Stream,只能传Enumeration;而Vector.elements()是最稳妥的获取方式(ArrayList没有elements()方法)Vector虽然线程安全但已过时,这里仅因 API 限制被迫使用,不是推荐通用容器别用
Arrays.asList(...).elements()—— 编译不过,asList返回的是Arrays.ArrayList,没有elements()方法
文件名排序错误会导致合并内容错乱
碎片文件(如 part1.dat、part10.dat、part2.dat)如果直接按字符串排序,"part10.dat" 会排在 "part2.dat" 前面——结果就是第 10 块内容插在第 2 块之前。
- 用正则提取数字再排序更可靠:
files.sort((f1, f2) -> { int n1 = Integer.parseInt(f1.getName().replaceAll("\D+", "")); int n2 = Integer.parseInt(f2.getName().replaceAll("\D+", "")); return Integer.compare(n1, n2); }); - 排序必须在创建
FileInputStream之前完成;一旦流打开,顺序就固化了
资源管理最容易漏掉的三个点
-
SequenceInputStream关闭时会自动关闭所有内部子流(FileInputStream),所以不要手动调用它们的close(),否则可能抛IOException: Stream closed - 用 try-with-resources 时,只声明
SequenceInputStream和FileOutputStream即可,子流交给它管 - 如果中间某一个
FileInputStream构造失败(比如文件不存在),整个流程就中断——建议提前校验文件存在性,或改用循环 +Files.copy()分段处理,异常粒度更细
SequenceInputStream 的核心约束很明确:单向、一次性、无缓冲、不支持 mark/reset。如果你需要断点续传、边读边校验、或中途跳过某块,它就不合适了——这时候该换 Files.copy() 配合 Files.list() 手动遍历,或者用 FileChannel.transferFrom() 控制 offset。











