Java InputStream to String

1. Overview

In this tutorial we’ll look at how to convert an InputStream to a String, using Guava, the Apache Commons IO library and plain Java.

2. Convert with Guava

Let’s start with a Guava example – leveraging the InputSupplier functionality:

@Test
public void givenUsingGuava_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    InputSupplier<InputStream> inputSupplier = new InputSupplier<InputStream>() {
        @Override
        public InputStream getInput() throws IOException {
            return inputStream;
        }
    };
    InputSupplier<InputStreamReader> readerSupplier = 
      CharStreams.newReaderSupplier(inputSupplier, Charsets.UTF_8);

    String text = CharStreams.toString(readerSupplier);

    assertThat(text, equalTo(originalString));
}

Let’s go over the steps:

  • first – we wrap our InputStream in an InputSupplier<InputStream> – and as far as I’m aware, this is the easiest way to do so
  • then – we use an InputStream parametrized with a reader – so that we may work with it as a character stream
  • finally – we use the Guava CharStreams utility to convert it to a String

Note that the final conversion operation – the CharStreams.toStringwill also close the InputStream correctly.

A simpler way of doing the conversion with Guava, but without the automatic closing of resources, would be:

@Test
public void givenUsingGuavaAndJava7_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    String text = null;
    try (final Reader reader = new InputStreamReader(inputStream)) {
        text = CharStreams.toString(reader);
    }

    assertThat(text, equalTo(originalString));
}

In this example, the CharStreams.toString method will not close the InputStream automatically – which is why we’re using the try-with-resources Java 7 functionality to do so.

3. Convert with Apache Commons IO

Let’s now look at how to do this with the Commons IO library.

An important caveat here is that – as opposed to Guava – neither of these examples will close the InputStream – which is why I personally prefer the Guava solution.

@Test
public void givenUsingCommonsIo_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    String text = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name());
    assertThat(text, equalTo(originalString));
}

We can also use a StringWriter to do the conversion:

@Test
public void givenUsingCommonsIoWithCopy_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    StringWriter writer = new StringWriter();
    String encoding = StandardCharsets.UTF_8.name();
    IOUtils.copy(inputStream, writer, encoding);

    assertThat(writer.toString(), equalTo(originalString));
}

4. Convert with Java – InputStream

Let’s look now at a lower level approach using plain Java – an InputStream and a simple StringBuilder:

@Test
public void givenUsingJava5_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(DEFAULT_SIZE);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    StringBuilder textBuilder = new StringBuilder();
    try (Reader reader = new BufferedReader(new InputStreamReader
      (inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) {
        int c = 0;
        while ((c = reader.read()) != -1) {
            textBuilder.append((char) c);
        }
    }
    assertEquals(textBuilder.toString(), originalString);
}

5. Convert with Java and a Scanner

Finally – let’s now look at a plain Java example – using a standard text Scanner:

@Test
public void givenUsingJava7_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    String text = null;
    try (Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) {
        text = scanner.useDelimiter("\\A").next();
    }

    assertThat(text, equalTo(originalString));
}

Note that the InputStream is going to be closed by the closing of the Scanner.

The only reason this is a Java 7 example, and not a Java 5 one is the use of the try-with-resources statement – turning that into a standard try-finally block will compile just fine with Java 5.

6. Conclusion

After compiling the best way to do the simple conversion – InputStream to String – in a correct and readable way – and after seeing so many wildly different answers and solutions – I think that a clear and concise best practice for this is called for.

The implementation of all these examples and code snippets can be found in my github project – this is an Eclipse based project, so it should be easy to import and run as it is.

Java 8 is out and about now - to keep track of everything, I will keep updating the Gran Kahuna of Java 8 Resources.

I usually post about Java stuff on Google+ - you should follow me there:

GET THE 3 EBOOKS >>
Download the 3 eBooks: "Rest with Spring", "Persistence with Spring" and "Learn HttpClient"
×
Build Your Web App with Spring (and quickly prototype it to 90%)

  • Greg Brown

    Why not just use an InputStreamReader and a StringBuilder? No 3rd-party libraries required.

    @Test
    public void testInputStreamToString() throws IOException {
    String originalString = “abcdefghijklmnop”;
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    StringBuilder textBuilder = new StringBuilder();
    try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream,
    Charset.forName(“UTF-8″))) {
    int c = 0;
    while ((c = inputStreamReader.read()) != -1) {
    textBuilder.append((char)c);
    }
    }

    Assert.assertEquals(textBuilder.toString(), originalString);
    }

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Greg, I did consider including a Java 5 style solution in the article – the only reason I didn’t at the time was that I didn’t like the idea of the explicit character by character approach for large Strings. I tested it out and it is indeed twice as slow as all the other options (just a quick empirical test). However, seeing how these micro-benchmarks aren’t all that usefull, I think you’re right – and I will include it in the article.
      Thanks for the feedback and the code sample – it’s not every day that someone actually pastes in a working one :)
      Cheers,
      Eugen.

      • Greg Brown

        Hi Eugen,
        That example was actually written for Java 7 (like your example, it uses try-with-resources). Of course, it could be easily modified to work with Java 5.
        I suspect that the other implementations use buffering to help make things faster. My example could probably be similarly optimized (maybe by using a BufferedReader).
        Greg

        • http://www.baeldung.com/ Eugen Paraschiv

          Yeah, I noticed the try with resources – and you’re right, as my other example, it can be easily modified to work with Java 5. As for the speed, I’m sure it can be optimized – but doing that early is probably not necessary, so I’m not focusing to much on that. Wrapping the raw reader in a BufferedReader may however be worth it.
          Cheers,
          Eugen.

  • Greg Brown

    Sorry about the formatting – Disqus appears to have ignored my spacing.