如何将多个不同的InputStream链接到一个InputStream中

我想知道是否有任何意识的方式链接多个InputStream到一个连续的Java(或斯卡拉)InputStream。

我需要的是parsing从FTP服务器通过networking加载的平面文件。 我想要做的是取文件[1..N],打开stream,然后将它们合并成一个stream。 所以当file1结束时,我想从file2开始读取等等,直到到达fileN的末尾。

我需要以特定的顺序读取这些文件,数据来自遗留系统,这些遗留系统会以barches方式生成文件,因此数据取决于另一个文件中的数据,但是我想将它们作为一个连续的stream处理,以简化我的域逻辑接口。

我search了四周,发现PipedInputStream,但我不积极,这是我所需要的。 一个例子会有帮助。

JDK就在这里! 引用SequenceInputStream JavaDoc :

SequenceInputStream表示其他inputstream的逻辑连接。 它从一个有序的inputstream集合开始,从第一个读取到文件结束,然后从第二个读取,依此类推,直到最后一个包含的inputstream达到文件结束。

你想连接任意数量的InputStreamSequenceInputStream只接受两个。 但是由于SequenceInputStream也是一个InputStream你可以recursion地应用它(嵌套它们):

 new SequenceInputStream( new SequenceInputStream( new SequenceInputStream(file1, file2), file3 ), file4 ); 

…你明白了。

也可以看看

  • 你如何在Java中合并两个inputstream? (DUP?)

这是使用SequencedInputStream完成的,在Tomasz Nurkiewicz的回答中显示,这在Java中很简单。 最近我不得不在一个项目中多次做这个,所以我通过“皮条客我的图书馆”模式增加了一些斯卡拉的善良。

 object StreamUtils { implicit def toRichInputStream(str: InputStream) = new RichInputStream(str) class RichInputStream(str: InputStream) { // a bunch of other handy Stream functionality, deleted def ++(str2: InputStream): InputStream = new SequenceInputStream(str, str2) } } 

有了这个,我可以做如下的stream式测序

 val mergedStream = stream1++stream2++stream3 

甚至

 val streamList = //some arbitrary-length list of streams, non-empty val mergedStream = streamList.reduceLeft(_++_) 

另一个解决scheme:首先创build一个inputstream的列表,然后创buildinputstream的序列:

 List<InputStream> iss = Files.list(Paths.get("/your/path")) .filter(Files::isRegularFile) .map(f -> { try { return new FileInputStream(f.toString()); } catch (Exception e) { throw new RuntimeException(e); } }).collect(Collectors.toList()); new SequenceInputStream(Collections.enumeration(iss))) 

这是一个更优雅的使用Vector的解决scheme,这是专门针对Android的,但是使用vector来处理任何Java

  AssetManager am = getAssets(); Vector v = new Vector(Constant.PAGES); for (int i = 0; i < Constant.PAGES; i++) { String fileName = "file" + i + ".txt"; InputStream is = am.open(fileName); v.add(is); } Enumeration e = v.elements(); SequenceInputStream sis = new SequenceInputStream(e); InputStreamReader isr = new InputStreamReader(sis); Scanner scanner = new Scanner(isr); // or use bufferedReader