1.概述

在本文中,我们将看一下StreamUtils类以及如何使用它。

简单地说,StreamUtils是Spring提供的一个工具类,它包含用于处理流一些实用方法。

这个流是指InputStream和OutputStream位于包java.io中,与Java 8的Stream API不相关。

2. Maven依赖

spring-core模块中提供了StreamUtils类,因此让我们将其添加到pom.xml中

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>

您可以在Maven中央存储库中找到该库的最新版本。

3.复制流

StreamUtils类包含几个名为copy()的重载方法以及其他一些变体:

  • copyRange()
  • copyToByteArray()
  • copyString()

我们可以在不使用任何库的情况下复制流。但是,代码比较繁琐,并且难以阅读和理解。

提示,为简单起见,示例的代码中省略了流的关闭。

3.1 直接复制

我们可以使用StreamUtils.copy()直接将输入流复制带输出流。

    @Test
    public void test_StreamUtils_copy() 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 = getStringFromInputStream(new FileInputStream(inputFileName));
        String outputFileContent = getStringFromInputStream(new FileInputStream(outputFileName));
        assertEquals(inputFileContent, outputFileContent);
    }

    public static String getStringFromInputStream(InputStream input) throws IOException {
        StringWriter writer = new StringWriter();
        IOUtils.copy(input, writer, "UTF-8");
        return writer.toString();
    }

getStringFromInputStream()是一个使用InputStream并将其内容作为String返回的方法。

3.2 复制指定范围

如果,不需要复制InputStream的全部内容,我们可以使用copyRange()方法将内容范围复制到给定的OutputStream

    @Test
    public void test_StreamUtils_copyRange() 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的长度怎么办?

copyRange()方法会复制到流的末尾。

3.3 复制字符串到输出流

让我们看看如何将String的内容复制到给定的OutputStream

    @Test
    public void test_StreamUtils_copyString() 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);
    }

复制字符串的StreamUtils.copy()方法、具有三个参数。分别是要复制的字符串,要用于写入文件的字符集和要将字符串的内容复制到的OutputStream

3.4 将输入流的内容复制到字符串

我们也可以给定InputStream的内容复制到新字符串。

    @Test
    public void test_StreamUtils_copyStringFromInputStream() 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);
    }

StreamUtils.copyToString()方法有两个参数,分别是输入流和字符串的字符集。

3.5 将给定字节数组复制到输出流

我们还可以将给定字节数组的内容复制到OutputStream

    public void test_StreamUtils_copyByteArrayToOutputStream() throws IOException {
        String outputFileName = "src/test/resources/output.txt";
        String string = ".";
        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);
    }

3.6 将输入流的内容复制字节数组

我们也可以将给定InputStream的内容复制到新的字节数组中:

    public void test_StreamUtils_copyInputStreamToByteArray() 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()方法。可以将InputStreamOutputStream作为参数传递给这个方法,以获取InputStreamOutputStream的变体,该变体将忽略对*close()*方法的调用:

public InputStream getNonClosingInputStream() throws IOException {
    InputStream in = new FileInputStream("src/test/resources/input.txt");
    return StreamUtils.nonClosing(in);
}

5. 总结

在本文中,我们了解了什么是StreamUtils

我们还介绍了StreamUtils类的所有方法,并且简单的介绍如何使用它们。

最后,往常一样,代码可以在Github上找到。