1. 概述
本文将深入探讨 Spring 的 StreamUtils
工具类及其使用方法。简单来说,StreamUtils
是 Spring 提供的一个实用工具类,专门用于处理 java.io
包中的 InputStream
和 OutputStream
流操作。⚠️ 注意:它和 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()
:复制字符串内容
虽然不用库也能实现流复制,但代码会非常繁琐且难以维护。注意:为简化示例,以下代码省略了流关闭操作。
3.1 输入流复制到输出流
@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);
}
✅ 执行后输出文件将包含输入流的全部内容。
3.2 复制指定范围内容
使用 copyRange()
复制输入流的指定范围到输出流:
@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);
}
⚠️ 如果指定范围超出输入流长度,方法会自动复制到流末尾。
3.3 字符串复制到输出流
@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);
}
参数说明:
- 待复制的字符串
- 字符编码(如
StandardCharsets.UTF_8
) - 目标输出流
3.4 输入流转换为字符串
@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);
}
3.5 字节数组与流互转
字节数组 → 输出流:
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);
}
输入流 → 字节数组:
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. 其他实用功能
4.1 清空流数据
使用 drain()
方法消耗输入流中的剩余数据:
StreamUtils.drain(in);
4.2 获取空输入流
通过 emptyInput()
获取高效的空输入流:
public InputStream getInputStream() {
return StreamUtils.emptyInput();
}
4.3 非关闭流包装
使用 nonClosing()
包装流,使其忽略 close()
调用:
public InputStream getNonClosingInputStream() throws IOException {
InputStream in = new FileInputStream("src/test/resources/input.txt");
return StreamUtils.nonClosing(in);
}
✅ 适用于需要保持流开启的场景(如 HTTP 响应流)。
5. 总结
本文全面介绍了 StreamUtils
的核心功能:
- 流复制操作(完整/范围/字符串/字节数组)
- 特殊流处理(清空/空流/非关闭流)
- 实际应用场景示例
完整代码示例可在 GitHub 仓库 查看。踩坑提醒:实际使用时务必记得关闭流,避免资源泄漏!