Easy Ways to Write a Java InputStream to an OutputStream

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)) > 0) {
        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>29.0-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.8.0</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.

The implementation of these examples is available over on GitHub.

Related posts:

Spring Data MongoDB – Indexes, Annotations and Converters
Filtering a Stream of Optionals in Java
Primitive Type Streams in Java 8
Một số tính năng mới về xử lý ngoại lệ trong Java 7
Tạo ứng dụng Java RESTful Client không sử dụng 3rd party libraries
Remove the First Element from a List
Spring Boot - Scheduling
Spring Boot - Runners
Using Optional with Jackson
Java Program to Implement Coppersmith Freivald’s Algorithm
Java Program to implement Bit Matrix
Java Program to Implement Binomial Tree
Java Program to Implement Brent Cycle Algorithm
Jackson – JsonMappingException (No serializer found for class)
Java Program to Implement Bresenham Line Algorithm
Functional Interface trong Java 8
Functional Interfaces in Java 8
Java Program to Solve Tower of Hanoi Problem using Stacks
OAuth2.0 and Dynamic Client Registration
Java Program to Search for an Element in a Binary Search Tree
Programmatic Transaction Management in Spring
Java Program to Implement Hash Tree
Java Program to Check if a Directed Graph is a Tree or Not Using DFS
Java Program to Implement Multi-Threaded Version of Binary Search Tree
Java Program to Implement Graham Scan Algorithm to Find the Convex Hull
A Quick Guide to Spring MVC Matrix Variables
Calling Stored Procedures from Spring Data JPA Repositories
Entity To DTO Conversion for a Spring REST API
Performance Difference Between save() and saveAll() in Spring Data
Java 8 – Powerful Comparison with Lambdas
Template Engines for Spring
Using the Map.Entry Java Class