1. 概述
在本文中,我们将介绍Spring中的StreamUtils类以及如何使用它。
简单地说,StreamUtils是一个Spring的工具类,它包含一些处理InputStream和OutputStream工具方法,与Java 8的Stream API无关。
2. Maven依赖
StreamUtils类属于spring-core模块,所以让我们将其添加到pom.xml中:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.13</version>
</dependency>
3. 复制流
StreamUtils类包含几个名为copy()的重载方法以及其他一些变体:
- copyRange()
- copyToByteArray()
- copyString()
我们可以在不使用任何第三方工具类的情况下复制流。然而代码会很麻烦,而且更难阅读和理解。
请注意,为了简单起见,我们省略流的关闭。
让我们看看如何将InputStream的内容复制到给定的OutputStream:
class CopyStreamIntegrationTest {
@Test
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(outputFileName);
StreamUtils.copy(in, out);
assertTrue(outputFile.exists());
String inputFileContent = CopyStream.getStringFromInputStream(new FileInputStream(inputFileName));
String outputFileContent = CopyStream.getStringFromInputStream(new FileInputStream(outputFileName));
assertEquals(inputFileContent, outputFileContent);
}
}
public class CopyStream {
public static String getStringFromInputStream(InputStream input) throws IOException {
StringWriter writer = new StringWriter();
IOUtils.copy(input, writer, "UTF-8");
return writer.toString();
}
}
创建的文件包含InputStream的内容。
我们也可以不复制InputStream的全部内容,使用copyRange()方法将指定范围的内容复制到给定的OutputStream:
class CopyStreamIntegrationTest {
@Test
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 = CopyStream.getStringFromInputStream(new FileInputStream(inputFileName));
String outputFileContent = CopyStream.getStringFromInputStream(new FileInputStream(outputFileName));
assertEquals(inputFileContent.substring(1, 11), outputFileContent);
}
}
正如我们在这里看到的,copyRange()方法接收四个参数,分别是InputStream、OutputStream、开始位置和结束位置。 如果指定的范围超过了InputStream的长度,则复制到流的末尾。
让我们看看如何将String的内容复制到给定的OutputStream:
class CopyStreamIntegrationTest {
@Test
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);
String outputFileContent = CopyStream.getStringFromInputStream(new FileInputStream(outputFileName));
assertTrue(outputFile.exists());
assertEquals(outputFileContent, string);
}
}
上例中方法copy()接收三个参数,分别是要复制的字符串、字符集以及我们要将字符串的内容复制到的OutputStream。
以下是我们如何将给定InputStream的内容复制到新字符串:
class CopyStreamIntegrationTest {
@Test
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 = CopyStream.getStringFromInputStream(new FileInputStream(inputFileName));
assertEquals(inputFileContent, content);
}
}
我们还可以将给定字节数组的内容复制到输出流:
class CopyStreamIntegrationTest {
@Test
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 = CopyStream.getStringFromInputStream(new FileInputStream(outputFileName));
assertEquals(outputFileContent, string);
}
}
或者,我们可以将给定InputStream的内容复制到新的字节数组中:
class CopyStreamIntegrationTest {
@Test
void whenCopyInputStreamToByteArray_thenCorrect() throws IOException {
String inputFileName = "src/test/resources/input.txt";
InputStream in = new FileInputStream(inputFileName);
byte[] out = StreamUtils.copyToByteArray(in);
String content = new String(out);
String inputFileContent = CopyStream.getStringFromInputStream(new FileInputStream(inputFileName));
assertEquals(inputFileContent, content);
}
}
4. 其他功能
InputStream可以作为参数传递给drain()方法以删除流中的所有剩余数据:
StreamUtils.drain(in);
我们还可以使用emptyInput()方法来获得一个高效的空InputStream:
public class DrainStream {
public InputStream getInputStream() {
return StreamUtils.emptyInput();
}
}
有两个名为nonClosing()的重载方法。 InputStream或OutputStream可以作为参数传递给这些方法,以获取忽略对close()方法调用的InputStream或OutputStream的变体:
public class CopyStream {
public InputStream getNonClosingInputStream() throws IOException {
InputStream in = new FileInputStream("src/test/resources/input.txt");
return StreamUtils.nonClosing(in);
}
}
5. 总结
在本教程中,我们了解了StreamUtils是什么。我们还介绍了StreamUtils类的所有方法,并了解了如何使用它们。
本文的完整代码可以在GitHub上找到。
与往常一样,本教程的完整源代码可在GitHub上获得。