![](/img/trans.png)
[英]How can I read different groups of data on the same InputStream, using different types of InputStreams for each of them?
[英]How to chain multiple different InputStreams into one InputStream
我想知道是否有任何想法的方法將多個InputStream鏈接到Java(或Scala)中的一個連續的InputStream中。
我需要它是解析我從FTP服務器通過網絡加載的平面文件。 我想要做的是獲取文件[1..N],打開流然后將它們組合成一個流。 所以當file1結束時,我想從file2開始讀取,依此類推,直到我到達fileN的末尾。
我需要按特定順序讀取這些文件,數據來自遺留系統,這些遺留系統會產生文件,因此一個數據依賴於另一個文件中的數據,但我想將它們作為一個連續流來處理,以簡化我的域邏輯接口。
我四處搜索並找到了PipedInputStream,但我並不認為這是我需要的。 一個例子會有所幫助。
它就在JDK中! 引用SequenceInputStream
JavaDoc :
SequenceInputStream
表示其他輸入流的邏輯串聯。 它從一個有序的輸入流集合開始,從第一個讀取到文件結束,然后從第二個讀取,依此類推,直到最后一個包含的輸入流到達文件末尾。
您希望連接任意數量的InputStream
而SequenceInputStream
只接受兩個。 但是由於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.