1. 概述
本文將介紹 StreamUtils 類及其使用方法。
簡單來説,StreamUtils 是 Spring 提供的類,其中包含一些用於處理流的實用方法,包括 InputStream 和 OutputStream,這些類位於 java.io 包中,與 Java 8 的 Stream API 無關。
2. Maven 依賴
StreamUtils 類位於 spring-core 模塊中,因此我們將其添加到我們的 pom.xml 中:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>您可以在 Maven 中央倉庫 找到該庫的最新版本。
3. 複製流
StreamUtils 類包含多個重載的方法,名為 copy(),以及其他一些變體:
- copyRange()
- copyToByteArray()
- copyString()
我們可以不使用任何庫來複制流。但是,代碼會變得笨拙且難以閲讀和理解。
請注意,為了簡化起見,我們省略了流的關閉。
讓我們看看如何將 InputStream 的內容複製到給定的 OutputStream:
@Test
public void whenCopyInputStreamToOutputStream_thenCorrect() throws IOException {
String inputFileName = "src/test/resources/input.txt";
String outputFileName = "src/test/resources/output.txt";
File outputFile = new File(outputFileName);
InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFile);
StreamUtils.copy(in, out);
assertTrue(outputFile.exists());
String inputFileContent = getStringFromInputStream(new FileInputStream(inputFileName));
String outputFileContent = getStringFromInputStream(new FileInputStream(outputFileName));
assertEquals(inputFileContent, outputFileContent);
}創建的文件包含 InputStream 的內容。
請注意,getStringFromInputStream() 是一個接受 InputStream 並返回其內容作為 String 的方法。該方法的實現可在代碼的完整版本中找到。
我們不必複製整個 InputStream 的內容,可以使用 copyRange() 方法將內容範圍複製到指定的 OutputStream。
@Test
public void whenCopyRangeOfInputStreamToOutputStream_thenCorrect() throws IOException {
String inputFileName = "src/test/resources/input.txt";
String outputFileName = "src/test/resources/output.txt";
File outputFile = new File(outputFileName);
InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFileName);
StreamUtils.copyRange(in, out, 1, 10);
assertTrue(outputFile.exists());
String inputFileContent = getStringFromInputStream(new FileInputStream(inputFileName));
String outputFileContent = getStringFromInputStream(new FileInputStream(outputFileName));
assertEquals(inputFileContent.substring(1, 11), outputFileContent);
}如我們所見,copyRange() 方法接受四個參數:InputStream、OutputStream、開始複製的位置和結束複製的位置。但是,如果指定的範圍超過 InputStream 的長度,該方法將複製到流的末尾。
下面我們來看如何將 String 的內容複製到給定的 OutputStream:
@Test
public void whenCopyStringToOutputStream_thenCorrect() throws IOException {
String string = "Should be copied to OutputStream.";
String outputFileName = "src/test/resources/output.txt";
File outputFile = new File(outputFileName);
OutputStream out = new FileOutputStream("src/test/resources/output.txt");
StreamUtils.copy(string, StandardCharsets.UTF_8, out);
assertTrue(outputFile.exists());
String outputFileContent = getStringFromInputStream(new FileInputStream(outputFileName));
assertEquals(outputFileContent, string);
}方法 copy() 接受三個參數:要複製的 String、我們希望用於寫入文件的 Charset,以及我們希望複製 String 內容的目標 OutputStream。
以下是如何將給定 InputStream 的內容複製到新的 String 的方法:
@Test
public void whenCopyInputStreamToString_thenCorrect() throws IOException {
String inputFileName = "src/test/resources/input.txt";
InputStream is = new FileInputStream(inputFileName);
String content = StreamUtils.copyToString(is, StandardCharsets.UTF_8);
String inputFileContent = getStringFromInputStream(new FileInputStream(inputFileName));
assertEquals(inputFileContent, content);
}我們還可以將給定的字節數組的內容複製到 OutputStream:
public void whenCopyByteArrayToOutputStream_thenCorrect() throws IOException {
String outputFileName = "src/test/resources/output.txt";
String string = "Should be copied to OutputStream.";
byte[] byteArray = string.getBytes();
OutputStream out = new FileOutputStream("src/test/resources/output.txt");
StreamUtils.copy(byteArray, out);
String outputFileContent = getStringFromInputStream(new FileInputStream(outputFileName));
assertEquals(outputFileContent, string);
}或者,我們可以將給定 InputStream 的內容複製到一個新的字節數組中:
public void whenCopyInputStreamToByteArray_thenCorrect() throws IOException {
String inputFileName = "src/test/resources/input.txt";
InputStream is = new FileInputStream(inputFileName);
byte[] out = StreamUtils.copyToByteArray(is);
String content = new String(out);
String inputFileContent = getStringFromInputStream(new FileInputStream(inputFileName));
assertEquals(inputFileContent, content);
}4. 其他功能
可以通過將一個 InputStream 作為參數傳遞給 drain() 方法,從而移除流中所有剩餘的數據:
StreamUtils.drain(in);我們還可以使用 emptyInput() 方法來獲取一個高效的空 InputStream:
public InputStream getInputStream() {
return StreamUtils.emptyInput();
}存在兩個重載方法,名為 nonClosing()。 可以將一個 InputStream 或 OutputStream 作為參數傳遞給這些方法,以獲得一個忽略 close() 方法調用的 InputStream 或 OutputStream 的變體。
public InputStream getNonClosingInputStream() throws IOException {
InputStream in = new FileInputStream("src/test/resources/input.txt");
return StreamUtils.nonClosing(in);
}5. 結論
在本快速教程中,我們已經瞭解了 StreamUtils 的作用。我們還涵蓋了 StreamUtils 類中的所有方法,並瞭解瞭如何使用它們。