Spring的StreamUtils介绍

2023/05/13

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上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章