將 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 上找到。