將 OutputStream 轉換為 InputStream
一、概述
InputStream和OutputStream是 Java IO 中的兩個基本類。有時,我們需要在這兩種流類型之間進行轉換。在較早的教程中,我們討論了將InputStream寫入OutputStream.
在本快速教程中,我們將朝相反的方向看。我們將探討如何將OutputStream轉換為InputStream.
二、問題簡介
有時,需要將OutputStream轉換為InputStream.這種轉換在各種情況下都很有用,例如當我們需要讀取已寫入OutputStream的數據時。
在本文中,我們將探討執行此轉換的兩種不同方式:
- 使用
byte數組 - 使用管道
為簡單起見,我們將在示例中使用ByteArrayOutputStream作為OutputStream類型。此外,我們將使用單元測試斷言來驗證我們是否可以從轉換後的InputStream對像中讀取預期數據。
那麼接下來,讓我們看看他們的行動。
3. 使用byte數組
當我們思考這個問題時,最直接的做法可能是:
- 第 1 步 – 從給定的
OutputStream讀取數據,並將數據保存在緩衝區中,例如byte數組 - 第 2 步 – 使用
byte數組創建InputStream
接下來,讓我們將這個想法作為測試來實現,並檢查它是否按預期工作:
@Test
void whenUsingByteArray_thenGetExpectedInputStream() throws IOException {
String content = "I'm an important message.";
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
out.write(content.getBytes());
try (ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray())) {
String inContent = new String(in.readAllBytes());
assertEquals(content, inContent);
}
}
}
首先,我們準備了一個OutputStream對象 ( out)並向其寫入了一個字符串 ( content )。接下來,我們通過調用**out.toByteArray()**從OutputStream獲取byte數組形式的數據,並從該數組創建一個InputStream 。
如果我們運行測試,它就會通過。所以轉換成功。
值得一提的是,我們使用try-with-resources來確保InputStream和OutputStream在讀寫操作後關閉。此外,我們的try塊沒有catch塊,因為我們已經聲明測試方法拋出IOException 。
這種方法簡單易行。然而,缺點是它需要將整個輸出存儲在內存中,然後才能將其作為輸入讀回。換句話說,如果輸出非常大,可能會導致大量內存消耗並可能導致OutOfMemoryError.
4.通過管道
我們經常一起使用PipedOutputStream和PipedInputStream類,以允許將數據從OutputStream傳遞到InputStream.因此,我們可以先連接一個PipedOutputStream和一個PipedInputStream ,這樣PipedInputStream就可以讀取來自PipedOutputStream的數據。接下來,我們可以將給定的OutputStream的數據寫入PipedOutputStream.然後,在另一邊,我們可以從PipedInputStream讀取數據。
接下來,讓我們將其實現為單元測試:
@Test
void whenUsingPipeStream_thenGetExpectedInputStream() throws IOException {
String content = "I'm going through the pipe.";
ByteArrayOutputStream originOut = new ByteArrayOutputStream();
originOut.write(content.getBytes());
//connect the pipe
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(in);
try (in) {
new Thread(() -> {
try (out) {
originOut.writeTo(out);
} catch (IOException iox) {
// ...
}
}).start();
String inContent = new String(in.readAllBytes());
assertEquals(content, inContent);
}
}
如上面的代碼所示,首先,我們準備了OutputStream ( originOut )。接下來,我們創建了一個PipedInputStream ( in ) 和一個PipedOutputStream ( out ) 並將它們連接起來。這樣,管道就建立起來了。
然後,我們使用ByteArrayOutputStream.writeTo()方法將數據從給定的OutputStream轉發到PipedOutputStream 。我們應該注意到,我們創建了一個新線程來將數據寫入PipedOutputStream 。這是因為不建議在同一線程中同時使用PipedInputStream和PipedOutputStream對象。這可能會導致死鎖。
最後,如果我們執行它,測試就會通過。因此OutputStream成功轉換為PipedInputStream 。
5.結論
在本文中,我們探索了兩種將OutputStream轉換為InputStream的方法:
-
byte數組作為緩衝區——這很簡單。但是,它有潛在的OutOfMemoryError風險 - 使用管道——將輸出寫入
PipedOutputStream使數據流向PipedInputStream
與往常一樣,此處提供的所有代碼片段都可以在 GitHub 上找到。