1. 概述
本文我们将学习如何将 InputStream 写入 OutputStream。我们先使用 Java 8、Java 9原生API实现,然后再演示通过第三方库 - Guava 以及 Apache Commons IO library 实现。
注意,Java 9、Guava 和 Apache Commons IO 提供的工具方法不会flush或关闭流。 因此,我们需要使用 try-with-resources 或 finally 块来管理这些资源。
2. 使用 Java 8
第一种方式,我们使用原生Java代码将 InputStream 内容拷贝到 OutputStream:
void copy(InputStream source, OutputStream target) throws IOException {
byte[] buf = new byte[8192];
int length;
while ((length = source.read(buf)) > 0) {
target.write(buf, 0, length);
}
}
这种方式很简单,我们按字节读取数据然后写入到OutputStream中。
3. 使用 Java 9
Java 9 新增了一个InputStream.transferTo()方法,能够实现我们的需求:
@Test
public void givenUsingJavaNine_whenCopyingInputStreamToOutputStream_thenCorrect() throws IOException {
String initialString = "Hello World!";
try (InputStream inputStream = new ByteArrayInputStream(initialString.getBytes());
ByteArrayOutputStream targetStream = new ByteArrayOutputStream()) {
inputStream.transferTo(targetStream);
assertEquals(initialString, new String(targetStream.toByteArray()));
}
}
注意:在处理文件流的时候,使用 Files.copy() 比使用 transferTo() 方法更高效。
4. 使用 Guava
下面,我们看下如何使用 Guava提供ByteStreams.copy()工具方法。
首先需要在pom.xml中引入guava依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
下面的测试示例中展示了如何使用 ByteStreams 拷贝数据:
@Test
public void givenUsingGuava_whenCopyingInputStreamToOutputStream_thenCorrect() throws IOException {
String initialString = "Hello World!";
try (InputStream inputStream = new ByteArrayInputStream(initialString.getBytes());
ByteArrayOutputStream targetStream = new ByteArrayOutputStream()) {
ByteStreams.copy(inputStream, targetStream);
assertEquals(initialString, new String(targetStream.toByteArray()));
}
}
5. 使用 Commons IO
最后,我们将使用 Commons IO 的IOUtils.copy()方法来完成这项任务。
pom.xml 中增加commons-io 依赖:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
IOUtils 使用示例:
@Test
public void givenUsingCommonsIO_whenCopyingInputStreamToOutputStream_thenCorrect() throws IOException {
String initialString = "Hello World!";
try (InputStream inputStream = new ByteArrayInputStream(initialString.getBytes());
ByteArrayOutputStream targetStream = new ByteArrayOutputStream()) {
IOUtils.copy(inputStream, targetStream);
assertEquals(initialString, new String(targetStream.toByteArray()));
}
}
备注: Commons IO 还提供了几个额外的方法处理 InputStream 和 OutputStream。**当需要拷贝的数据超过2GB的时候,应该使用IOUtils.copyLarge()**。
6. 总结
本文我们学习了如何从InputStream中复制数据到OutputStream的几种方法。
本文示例中的代码存放在 GitHub。