1. Overview
In this quick tutorial, weβre going to learn how to write a Java InputStream to a Java OutputStream. Weβll first use core functionality from Java 8 and Java 9. Then, weβll look at a couple of external libraries β Guava and the Apache Commons IO library.
The utility methods provided by Java 9, Guava, and Apache Commons IO do not flush or close the streams. So, weβll need to manage these resources by using try-with-resources or a finally block.
2. Using Java 8
First, weβll begin by creating a simple method using vanilla Java to copy the content from the InputStream to the OutputStream:
void copy(InputStream source, OutputStream target) throws IOException {
byte[] buf = new byte[8192];
int length;
while ((length = source.read(buf)) != -1) {
target.write(buf, 0, length);
}
}
This code is pretty straightforward β weβre simply reading in some bytes and then writing them out.
3. Using Java 9
Java 9 provides a utility method, InputStream.transferTo(), for this task.
Letβs look at how we would use the transferTo() method:
@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()));
}
}
Note that when working with file streams, itβs more efficient to use Files.copy() than the transferTo() method.
4. Using Guava
Next, letβs look at how we would use Guavaβs utility method ByteStreams.copy().
Weβll need to include the guava dependency in our pom.xml:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.2.1-jre</version>
</dependency>
Letβs create a simple test case to show how we could use ByteStreams to copy data:
@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. Using Commons IO
Finally, letβs look at how we would use the Commons IO IOUtils.copy() method for this task.
Of course, weβll need to add the commons-io dependency to the pom.xml:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.15.1</version>
</dependency>
Letβs create a simple test case using IOUtils to copy data from the input stream to the output stream:
@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()));
}
}
Note: Commons IO provides additional methods for working with InputStreams and OutputStreams. IOUtils.copyLarge() should be used whenever it is necessary to copy 2 GB or more of data.
6. Conclusion
In this article, we explored simple ways to copy data from an InputStream to an OutputStream.
