Convert InputStream into a String in Java

Convert InputStream into a String in Java

The InputStream class is a high-level class representing any input byte stream in Java. Various subclasses further specify its usage, such as the BufferedInputStream, ByteArrayInputStream, SequenceInputStream, etc.

Needles to say, an InputStream can store any data and in some cases, they store String contents as a byte stream.

In this tutorial, we'll take a look at how to convert an InputStream into a Java String.

Let's start off by making an InputStream that we'll be using throughout the examples. These can come from various sources, but let's make one from a String, to make it easy to verify if the output is correct:

String string = "Input data, to be converted into an InputStream.";
InputStream inputStream = new ByteArrayInputStream(string.getBytes());

InputStream is an abstract class, and we've used one of its subclasses, ByteArrayInputStream to read the bytes of the String. Now, we've got an InputStream playing the role of actual input, that we can easily verify by comparing to the string instance.

Java has a plethora of classes to work with byte streams, and there's no shortage of options and approaches here. We'll be focusing on a few of them:

InputStream to String with InputStream.readAllBytes()

Since Java 9, this process has been simplified a lot. The InputStream is very commonly instantiated as a ByteArrayInputStream, before toByteArray() is called to retrieve the bytes from it.

This process is streamlined and replaced by the built-in InputStream.readAllBytes() method, which simply returns the bytes from the InputStream - a much-needed utility method.

The String class accepts a byte array into its constructor, out of which, a String is formed and returned, which makes this the easiest and most readable approach to convert an InputStream into a String:

String result = new String(inputStream.readAllBytes());
System.out.println(result);

This results in:

Input data, to be converted into an InputStream.

Note: If the InputStream contains more than Integer.MAX_VALUE bytes, the method naturally throws an OutOfMemoryError.

InputStream to String with ByteArrayOutputStream

For versions prior to Java 9, the fastest way to convert an InputStream into a String is by using the ByteArrayOutputStream.

This approach relies on the fact that we can easily construct Strings from byte arrays, and the fact that ByteArrayOutputStream has a very handy toString() method.

This process is practically the reverse of what we did in the beginning - constructing an InputStream from a String:

// Instantiate an OutputStream that'll store the data from the InputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

// For each line of the InputStream, write it to the OutputStream, and move to the next
for (int data = inputStream.read(); data != -1; data = inputStream.read()) {
    byteArrayOutputStream.write(data);
}

// Convert byte array into String
// Optional: You can set a character set via `StandardCharsets` here
String result = byteArrayOutputStream.toString(StandardCharsets.UTF_8);
System.out.println(result);

The inputStream.read() method reads the next byte in the array, starting at the first one. Here, we save a reference to the first byte as a data of that reading operation, check if it's -1 (reached the end of the stream) and move to the next byte with another read() operation.

Running this code results in:

Input data, to be converted into an InputStream.

InputStream to String with InputStreamReader

The InputStream and OutputStream classes are a part of the java.io package, which also includes a really handy InputStreamReader class, originally meant as the class to use to read InputStreams.

The InputStreamReader reads the bytes from the stream and decodes them into characters, for which you can optionally also specify via a StandardCharsets enumeration:

// Read the InputStream into a Reader
Reader reader = new InputStreamReader(inputStream);

// Instantiate a StringBuilder to save the result
StringBuilder result = new StringBuilder();

// Read each byte and convert into a char, adding to the StringBuilder
for (int data = reader.read(); data != -1; data = reader.read()) {
    result.append((char)data);
}

// Convert StringBuilder to String
System.out.println(result.toString());

This also results in:

Input data, to be converted into an InputStream.

InputStream to String with BufferedReader

Instead of a Reader, you can also use a BufferedReader. A BufferedReader stores larger amounts of bytes in a buffer before performing any reading/writing operations. Due to less context switching, this is a more efficient way to read and write large amounts of data, while on smaller amounts, the difference is unnoticeable.

In the previous example, we could've wrapped the InputStreamReader into a BufferedReader instead:

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

StringBuilder sb = new StringBuilder();

for (int data = reader.read(); data != -1; data = reader.read()) {
    sb.append((char)data);
}

System.out.println(sb.toString());

Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

This results in the same output:

Input data, to be converted into an InputStream.

Note: This approach is preferred over the previous one, due to the increased efficiency, even though it may be unnoticeable on smaller amounts of data.

InputStream to String with BufferedReader.lines()

With Java 8, the BufferedReader class got a new lines() method, which returns a Stream of Strings, for each line. This makes it effortless to read an InputStream, using the Stream API:

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

String result = reader.lines().collect(Collectors.joining(System.lineSeparator()));

System.out.println(result);

The Collectors.joining() method can work without us specifying a delimiter, though, it can lead to unexpected results when the input data has new lines. By setting the delimiter to System.lineSeparator(), we're allowing the underlying system's mechanism to kick in for the ends of lines.

This code results in:

Input data, to be converted into an InputStream.

InputStream to String with Apache Commons

Finally, let's take a look at how to achieve this through an external library - Apache Commons, which is present in a significant number of projects.

To use Apache Commons, we'll have to add its dependency to our own project:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
</dependency>

And with that out of the way, we can utilize its IOUtils class:

String result = IOUtils.toString(inputStream);
System.out.println(result);

The method also accepts an optional StandardCharsets enumeration:

String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

Running this code results in:

Input data, to be converted into an InputStream.

Conclusion

In this tutorial, we've taken a look at how to convert an InputStream into a String in Java.

We've taken a look at the newest approach, by reading all bytes and constructing a String directly, as well as writing them into a ByteArrayOutputStream, before using a Reader and BufferedReader and finally topping it off with the use of Apache Commons' IOUtils.

Last Updated: April 28th, 2021
Was this article helpful?

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

Want a remote job?

    Prepping for an interview?

    • Improve your skills by solving one coding problem every day
    • Get the solutions the next morning via email
    • Practice on actual problems asked by top companies, like:
     
     
     

    Better understand your data with visualizations

    With over 330+ pages, you'll learn the ins and outs of visualizing data in Python with popular libraries like Matplotlib, Seaborn, Bokeh, and more.

    © 2013-2021 Stack Abuse. All rights reserved.