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.
Needless 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() - Best Approach
- InputStream to String with ByteArrayOutputStream
- InputStream to String with InputStreamReader
- InputStream to String with BufferedReader.lines()
- InputStream to String with Apache Commons
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 InputStream
s.
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!
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());
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 String
s, 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
.