簡體   English   中英

如何將多個不同的InputStream鏈接到一個InputStream中

[英]How to chain multiple different InputStreams into one InputStream

我想知道是否有任何想法的方法將多個InputStream鏈接到Java(或Scala)中的一個連續的InputStream中。

我需要它是解析我從FTP服務器通過網絡加載的平面文件。 我想要做的是獲取文件[1..N],打開流然后將它們組合成一個流。 所以當file1結束時,我想從file2開始讀取,依此類推,直到我到達fileN的末尾。

我需要按特定順序讀取這些文件,數據來自遺留系統,這些遺留系統會產生文件,因此一個數據依賴於另一個文件中的數據,但我想將它們作為一個連續流來處理,以簡化我的域邏輯接口。

我四處搜索並找到了PipedInputStream,但我並不認為這是我需要的。 一個例子會有所幫助。

它就在JDK中! 引用SequenceInputStream JavaDoc

SequenceInputStream表示其他輸入流的邏輯串聯。 它從一個有序的輸入流集合開始,從第一個讀取到文件結束,然后從第二個讀取,依此類推,直到最后一個包含的輸入流到達文件末尾。

您希望連接任意數量的InputStreamSequenceInputStream只接受兩個。 但是由於SequenceInputStream也是一個InputStream你可以遞歸地應用它(嵌套它們):

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

......你明白了。

也可以看看

這是使用SequencedInputStream完成的,這在Java中是直截了當的,正如Tomasz Nurkiewicz的答案所示。 我最近不得不在一個項目中反復這樣做,所以我通過“pimp my library”模式添加了一些Scala-y善良。

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)
  }
}

有了這個,我可以按如下方式進行流測序

val mergedStream = stream1++stream2++stream3

甚至

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

另一種解決方案:首先創建輸入流列表,然后創建輸入流序列:

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的更優雅的解決方案,這是專門為Android而使用任何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

這是一個連接Iterator[InputStream]的簡單Scala版本:

import java.io.{InputStream, SequenceInputStream}
import scala.collection.JavaConverters._

def concatInputStreams(streams: Iterator[InputStream]): InputStream =
  new SequenceInputStream(streams.asJavaEnumeration)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM