4768

If you have a java.io.InputStream object, how should you process that object and produce a String?


Suppose I have an InputStream that contains text data, and I want to convert it to a String, so for example I can write that to a log file.

What is the easiest way to take the InputStream and convert it to a String?

public String convertStreamToString(InputStream is) {
// ???
}
Ramesh R
7,0874 gold badges27 silver badges40 bronze badges
asked Nov 21, 2008 at 16:47
3
  • Does this answer your question? Scanner is skipping nextLine() after using next() or nextFoo()? Commented Oct 8, 2020 at 14:02
  • 2
    Remember that you need to take the encoding of the input stream in consideration. The system default is not necessarily always the one you wan.t Commented Oct 30, 2020 at 9:52
  • 26
    Most of these answers were written pre-Java 9, but now you can get a byte array from the InputStream using .readAllBytes. So, simply "new String(inputStream.readAllBytes())" works using String's byte[] constructor. Commented May 28, 2021 at 21:19

67 Answers 67

1
2 3
3592

To summarize the other answers, I found 11 main ways to do this (see below). And I wrote some performance tests (see results below):

Ways to convert an InputStream to a String:

  1. Using IOUtils.toString (Apache Utils)

     String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
    
  2. Using CharStreams (Guava)

     String result = CharStreams.toString(new InputStreamReader(
     inputStream, Charsets.UTF_8));
    
  3. Using Scanner (JDK)

     Scanner s = new Scanner(inputStream).useDelimiter("\\A");
     String result = s.hasNext() ? s.next() : "";
    
  4. Using Stream API (Java 8). Warning: This solution converts different line breaks (like \r\n) to \n.

     String result = new BufferedReader(new InputStreamReader(inputStream))
     .lines().collect(Collectors.joining("\n"));
    
  5. Using parallel Stream API (Java 8). Warning: This solution converts different line breaks (like \r\n) to \n.

     String result = new BufferedReader(new InputStreamReader(inputStream))
     .lines().parallel().collect(Collectors.joining("\n"));
    
  6. Using InputStreamReader and StringBuilder (JDK)

     int bufferSize = 1024;
     char[] buffer = new char[bufferSize];
     StringBuilder out = new StringBuilder();
     Reader in = new InputStreamReader(stream, StandardCharsets.UTF_8);
     for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) {
     out.append(buffer, 0, numRead);
     }
     return out.toString();
    
  7. Using StringWriter and IOUtils.copy (Apache Commons)

     StringWriter writer = new StringWriter();
     IOUtils.copy(inputStream, writer, "UTF-8");
     return writer.toString();
    
  8. Using ByteArrayOutputStream and inputStream.read (JDK)

     ByteArrayOutputStream result = new ByteArrayOutputStream();
     byte[] buffer = new byte[1024];
     for (int length; (length = inputStream.read(buffer)) != -1; ) {
     result.write(buffer, 0, length);
     }
     // StandardCharsets.UTF_8.name() > JDK 7
     return result.toString("UTF-8");
    
  9. Using BufferedReader (JDK). Warning: This solution converts different line breaks (like \n\r) to line.separator system property (for example, in Windows to "\r\n").

     String newLine = System.getProperty("line.separator");
     BufferedReader reader = new BufferedReader(
     new InputStreamReader(inputStream));
     StringBuilder result = new StringBuilder();
     for (String line; (line = reader.readLine()) != null; ) {
     if (result.length() > 0) {
     result.append(newLine);
     }
     result.append(line);
     }
     return result.toString();
    
  10. Using BufferedInputStream and ByteArrayOutputStream (JDK)

    BufferedInputStream bis = new BufferedInputStream(inputStream);
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    for (int result = bis.read(); result != -1; result = bis.read()) {
     buf.write((byte) result);
    }
    // StandardCharsets.UTF_8.name() > JDK 7
    return buf.toString("UTF-8");
    
  11. Using inputStream.read() and StringBuilder (JDK). Warning: This solution has problems with Unicode, for example with Russian text (works correctly only with non-Unicode text)

    StringBuilder sb = new StringBuilder();
    for (int ch; (ch = inputStream.read()) != -1; ) {
     sb.append((char) ch);
    }
    return sb.toString();
    

Warning:

  1. Solutions 4, 5 and 9 convert different line breaks to one.

  2. Solution 11 can't work correctly with Unicode text

Performance tests

Performance tests for small String (length = 175), url in github (mode = Average Time, system = Linux, score 1,343 is the best):

 Benchmark Mode Cnt Score Error Units
 8. ByteArrayOutputStream and read (JDK) avgt 10 1,343 ± 0,028 us/op
 6. InputStreamReader and StringBuilder (JDK) avgt 10 6,980 ± 0,404 us/op
10. BufferedInputStream, ByteArrayOutputStream avgt 10 7,437 ± 0,735 us/op
11. InputStream.read() and StringBuilder (JDK) avgt 10 8,977 ± 0,328 us/op
 7. StringWriter and IOUtils.copy (Apache) avgt 10 10,613 ± 0,599 us/op
 1. IOUtils.toString (Apache Utils) avgt 10 10,605 ± 0,527 us/op
 3. Scanner (JDK) avgt 10 12,083 ± 0,293 us/op
 2. CharStreams (guava) avgt 10 12,999 ± 0,514 us/op
 4. Stream Api (Java 8) avgt 10 15,811 ± 0,605 us/op
 9. BufferedReader (JDK) avgt 10 16,038 ± 0,711 us/op
 5. parallel Stream Api (Java 8) avgt 10 21,544 ± 0,583 us/op

Performance tests for big String (length = 50100), url in github (mode = Average Time, system = Linux, score 200,715 is the best):

 Benchmark Mode Cnt Score Error Units
 8. ByteArrayOutputStream and read (JDK) avgt 10 200,715 ± 18,103 us/op
 1. IOUtils.toString (Apache Utils) avgt 10 300,019 ± 8,751 us/op
 6. InputStreamReader and StringBuilder (JDK) avgt 10 347,616 ± 130,348 us/op
 7. StringWriter and IOUtils.copy (Apache) avgt 10 352,791 ± 105,337 us/op
 2. CharStreams (guava) avgt 10 420,137 ± 59,877 us/op
 9. BufferedReader (JDK) avgt 10 632,028 ± 17,002 us/op
 5. parallel Stream Api (Java 8) avgt 10 662,999 ± 46,199 us/op
 4. Stream Api (Java 8) avgt 10 701,269 ± 82,296 us/op
10. BufferedInputStream, ByteArrayOutputStream avgt 10 740,837 ± 5,613 us/op
 3. Scanner (JDK) avgt 10 751,417 ± 62,026 us/op
11. InputStream.read() and StringBuilder (JDK) avgt 10 2919,350 ± 1101,942 us/op

Graphs (performance tests depending on Input Stream length in Windows 7 system)
enter image description here

Performance test (Average Time) depending on Input Stream length in Windows 7 system:

 length 182 546 1092 3276 9828 29484 58968
 test8 0.38 0.938 1.868 4.448 13.412 36.459 72.708
 test4 2.362 3.609 5.573 12.769 40.74 81.415 159.864
 test5 3.881 5.075 6.904 14.123 50.258 129.937 166.162
 test9 2.237 3.493 5.422 11.977 45.98 89.336 177.39
 test6 1.261 2.12 4.38 10.698 31.821 86.106 186.636
 test7 1.601 2.391 3.646 8.367 38.196 110.221 211.016
 test1 1.529 2.381 3.527 8.411 40.551 105.16 212.573
 test3 3.035 3.934 8.606 20.858 61.571 118.744 235.428
 test2 3.136 6.238 10.508 33.48 43.532 118.044 239.481
 test10 1.593 4.736 7.527 20.557 59.856 162.907 323.147
 test11 3.913 11.506 23.26 68.644 207.591 600.444 1211.545
answered Feb 17, 2016 at 0:58
10
  • 1
    Nice work. Could be useful to provide a tl;dr summary at the bottom, i.e. throwing out the solutions that have problems with line breaks / unicode and then (out of those that remain) saying which is fastest with or without external libraries. Commented Aug 1, 2020 at 11:16
  • 3
    I was curious about the Java 9 InputStream.transferTo and Java 10 Reader.transferTo solutions that were added since this answer was posted, so I checked out the linked code and added benchmarks for them. I only tested the "big string" benchmarks. InputStream.transferTo was the fastest of all the solutions tested, running in 60% of the time as test8 did on my machine. Reader.transferTo was slower than test8, but faster than all the other tests. That said, it ran in 95% of the time as test1, so it's not a significant improvement. Commented Nov 19, 2020 at 8:03
  • 2
    I converted all the while loops to for loops in an edit to this post, to avoid polluting the namespace with a variable that isn't used outside the loop. It's a neat trick that works in most Java reader/writer loops. Commented Feb 28, 2021 at 2:10
  • 34
    With Java 9 you can get a byte array from the InputStream using .readAllBytes. So "new String(inputStream.readAllBytes())" works using String's byte[] constructor. Commented May 28, 2021 at 21:18
  • Is 11 buffered? If not, the chunks may be small and what is seen is simply the additional overhead from the extra calls. Commented Oct 10, 2022 at 0:11
2762

A nice way to do this is using Apache Commons IOUtils to copy the InputStream into a StringWriter... Something like

StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();

or even

// NB: does not close inputStream, you'll have to use try-with-resources for that
String theString = IOUtils.toString(inputStream, encoding);

Alternatively, you could use ByteArrayOutputStream if you don't want to mix your Streams and Writers.

Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered Nov 21, 2008 at 16:54
2
  • Did the toString get deprecated? I see IOUtils.convertStreamToString() Commented Jul 2, 2020 at 15:26
  • I added an edit to include a searchable link to the actual source code itself as a reference. I believe this augments the answer for those who want to see how the command works. Commented Jul 6, 2021 at 0:03
2369

Here's a way using only the standard Java library (note that the stream is not closed, your mileage may vary).

static String convertStreamToString(java.io.InputStream is) {
 java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
 return s.hasNext() ? s.next() : "";
}

I learned this trick from "Stupid Scanner tricks" article. The reason it works is because Scanner iterates over tokens in the stream, and in this case we separate tokens using "beginning of the input boundary" (\A), thus giving us only one token for the entire contents of the stream.

Note, if you need to be specific about the input stream's encoding, you can provide the second argument to Scanner constructor that indicates what character set to use (e.g. "UTF-8").

Hat tip goes also to Jacob, who once pointed me to the said article.

Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered Mar 26, 2011 at 20:40
2
  • Shouldn't we close the scanner before returning the value? Commented Oct 19, 2020 at 6:13
  • would do the same and close the resource with try with resource try( java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A")){ return s.hasNext() ? s.next() : ""; } Commented Aug 31, 2022 at 22:17
894

Apache Commons allows:

String myString = IOUtils.toString(myInputStream, "UTF-8");

Of course, you could choose other character encodings besides UTF-8.

Note: From Java versions 1.7 and upwards, you can use StandardCharsets class for charsets instead of hardcoding as "UTF-8".(ex: StandardCharsets.UTF_8)

Also see: (documentation)

Kasun Siyambalapitiya
4,4539 gold badges43 silver badges60 bronze badges
answered Dec 8, 2008 at 20:13
2
  • 1
    Trying to get back InputStream, not working stackoverflow.com/q/66349701/3425489 Commented Feb 24, 2021 at 12:06
  • If you want to handle byte-order marks (BOM), use BOMInputStream bis = new BOMInputStream(Files.newInputStream(path)); String data = bis.hasBOM() ? IOUtils.toString(bis, bis.getBOMCharsetName()) : IOUtils.toString(bis); Commented May 22, 2024 at 7:47
323

Taking into account file one should first get a java.io.Reader instance. This can then be read and added to a StringBuilder (we don't need StringBuffer if we are not accessing it in multiple threads, and StringBuilder is faster). The trick here is that we work in blocks, and as such don't need other buffering streams. The block size is parameterized for run-time performance optimization.

public static String slurp(final InputStream is, final int bufferSize) {
 final char[] buffer = new char[bufferSize];
 final StringBuilder out = new StringBuilder();
 try (Reader in = new InputStreamReader(is, "UTF-8")) {
 for (;;) {
 int rsz = in.read(buffer, 0, buffer.length);
 if (rsz < 0)
 break;
 out.append(buffer, 0, rsz);
 }
 }
 catch (UnsupportedEncodingException ex) {
 /* ... */
 }
 catch (IOException ex) {
 /* ... */
 }
 return out.toString();
}
0
272

Use:

InputStream in = /* Your InputStream */;
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String read;
while ((read=br.readLine()) != null) {
 //System.out.println(read);
 sb.append(read);
}
br.close();
return sb.toString();
Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered Aug 4, 2011 at 8:29
1
  • 2
    readLine() removes the line feed character so the resulting string will contain no line breaks unless you add a line separator between each line you add to the builder. Commented Mar 15, 2021 at 22:11
197

For completeness here is Java 9 solution:

public static String toString(InputStream input) throws IOException {
 return new String(input.readAllBytes(), StandardCharsets.UTF_8);
}

This uses the readAllBytes method which was added to Java 9.

M. Justin
22.8k12 gold badges133 silver badges167 bronze badges
answered Sep 2, 2015 at 11:50
5
  • 4
    I benchmarked this here, and found this to be the fastest solution on my machine, running in about 60% the time of the next-fastest solution benchmarked. Commented Nov 19, 2020 at 8:05
  • >This method blocks until all remaining bytes have been read and end of stream is detected, or an exception is thrown. Commented Dec 13, 2021 at 19:35
  • 2
    @MartinMeeser all solutions on this page do, as it is part of the task. Commented Sep 16, 2022 at 14:52
  • @Holger read=br.readLine() WILL NOT block until all bytes are read or end of line is detected, InputStream.read will read one byte or given buffer size, difference to readAllBytes is quite impactfull Commented Sep 20, 2022 at 6:12
  • 2
    @MartinMeeser the task is to read the entire InputStream into one string. Of course, you can split it into multiple steps which are not reading the entire stream, but that is pointless when all you are doing with those steps, is to reassemble the partial results into a single result after the entire stream has been read. So, none of the solutions to this specific task will return before the entire stream has been read. Commented Sep 20, 2022 at 6:37
186

If you are using Google-Collections/Guava you could do the following:

InputStream stream = ...
String content = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
Closeables.closeQuietly(stream);

Note that the second parameter (i.e. Charsets.UTF_8) for the InputStreamReader isn't necessary, but it is generally a good idea to specify the encoding if you know it (which you should!)

ralfoide
3,0734 gold badges27 silver badges22 bronze badges
answered Jul 13, 2010 at 15:56
0
138

This is the best pure Java solution that fits perfectly for Android and any other JVM.

This solution works amazingly well... it is simple, fast, and works on small and large streams just the same!! (see benchmark above.. No. 8)

public String readFullyAsString(InputStream inputStream, String encoding)
 throws IOException {
 return readFully(inputStream).toString(encoding);
}
public byte[] readFullyAsBytes(InputStream inputStream)
 throws IOException {
 return readFully(inputStream).toByteArray();
}
private ByteArrayOutputStream readFully(InputStream inputStream)
 throws IOException {
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 byte[] buffer = new byte[1024];
 int length = 0;
 while ((length = inputStream.read(buffer)) != -1) {
 baos.write(buffer, 0, length);
 }
 return baos;
}
answered May 8, 2012 at 20:24
0
83

Use:

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
public static String readInputStreamAsString(InputStream in)
 throws IOException {
 BufferedInputStream bis = new BufferedInputStream(in);
 ByteArrayOutputStream buf = new ByteArrayOutputStream();
 int result = bis.read();
 while(result != -1) {
 byte b = (byte)result;
 buf.write(b);
 result = bis.read();
 }
 return buf.toString();
}
Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered Jun 10, 2009 at 21:07
0
68

Here's the most elegant, pure-Java (no library) solution I came up with after some experimentation:

public static String fromStream(InputStream in) throws IOException
{
 BufferedReader reader = new BufferedReader(new InputStreamReader(in));
 StringBuilder out = new StringBuilder();
 String newLine = System.getProperty("line.separator");
 String line;
 while ((line = reader.readLine()) != null) {
 out.append(line);
 out.append(newLine);
 }
 return out.toString();
}
answered Jan 1, 2013 at 3:43
0
67

I did a benchmark upon 14 distinct answers here (sorry for not providing credits but there are too many duplicates).

The result is very surprising. It turns out that Apache IOUtils is the slowest and ByteArrayOutputStream is the fastest solutions:

So first here is the best method:

public String inputStreamToString(InputStream inputStream) throws IOException {
 try(ByteArrayOutputStream result = new ByteArrayOutputStream()) {
 byte[] buffer = new byte[1024];
 int length;
 while ((length = inputStream.read(buffer)) != -1) {
 result.write(buffer, 0, length);
 }
 return result.toString(UTF_8);
 }
}

Benchmark results, of 20 MB random bytes in 20 cycles

Time in milliseconds

  • ByteArrayOutputStreamTest: 194
  • NioStream: 198
  • Java9ISTransferTo: 201
  • Java9ISReadAllBytes: 205
  • BufferedInputStreamVsByteArrayOutputStream: 314
  • ApacheStringWriter2: 574
  • GuavaCharStreams: 589
  • ScannerReaderNoNextTest: 614
  • ScannerReader: 633
  • ApacheStringWriter: 1544
  • StreamApi: Error
  • ParallelStreamApi: Error
  • BufferReaderTest: Error
  • InputStreamAndStringBuilder: Error

Benchmark source code

import com.google.common.io.CharStreams;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
/**
 * Created by Ilya Gazman on 2/13/18.
 */
public class InputStreamToString {
 private static final String UTF_8 = "UTF-8";
 public static void main(String... args) {
 log("App started");
 byte[] bytes = new byte[1024 * 1024];
 new Random().nextBytes(bytes);
 log("Stream is ready\n");
 try {
 test(bytes);
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 private static void test(byte[] bytes) throws IOException {
 List<Stringify> tests = Arrays.asList(
 new ApacheStringWriter(),
 new ApacheStringWriter2(),
 new NioStream(),
 new ScannerReader(),
 new ScannerReaderNoNextTest(),
 new GuavaCharStreams(),
 new StreamApi(),
 new ParallelStreamApi(),
 new ByteArrayOutputStreamTest(),
 new BufferReaderTest(),
 new BufferedInputStreamVsByteArrayOutputStream(),
 new InputStreamAndStringBuilder(),
 new Java9ISTransferTo(),
 new Java9ISReadAllBytes()
 );
 String solution = new String(bytes, "UTF-8");
 for (Stringify test : tests) {
 try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
 String s = test.inputStreamToString(inputStream);
 if (!s.equals(solution)) {
 log(test.name() + ": Error");
 continue;
 }
 }
 long startTime = System.currentTimeMillis();
 for (int i = 0; i < 20; i++) {
 try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
 test.inputStreamToString(inputStream);
 }
 }
 log(test.name() + ": " + (System.currentTimeMillis() - startTime));
 }
 }
 private static void log(String message) {
 System.out.println(message);
 }
 interface Stringify {
 String inputStreamToString(InputStream inputStream) throws IOException;
 default String name() {
 return this.getClass().getSimpleName();
 }
 }
 static class ApacheStringWriter implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 StringWriter writer = new StringWriter();
 IOUtils.copy(inputStream, writer, UTF_8);
 return writer.toString();
 }
 }
 static class ApacheStringWriter2 implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 return IOUtils.toString(inputStream, UTF_8);
 }
 }
 static class NioStream implements Stringify {
 @Override
 public String inputStreamToString(InputStream in) throws IOException {
 ReadableByteChannel channel = Channels.newChannel(in);
 ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 16);
 ByteArrayOutputStream bout = new ByteArrayOutputStream();
 WritableByteChannel outChannel = Channels.newChannel(bout);
 while (channel.read(byteBuffer) > 0 || byteBuffer.position() > 0) {
 byteBuffer.flip(); //make buffer ready for write
 outChannel.write(byteBuffer);
 byteBuffer.compact(); //make buffer ready for reading
 }
 channel.close();
 outChannel.close();
 return bout.toString(UTF_8);
 }
 }
 static class ScannerReader implements Stringify {
 @Override
 public String inputStreamToString(InputStream is) throws IOException {
 java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
 return s.hasNext() ? s.next() : "";
 }
 }
 static class ScannerReaderNoNextTest implements Stringify {
 @Override
 public String inputStreamToString(InputStream is) throws IOException {
 java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
 return s.next();
 }
 }
 static class GuavaCharStreams implements Stringify {
 @Override
 public String inputStreamToString(InputStream is) throws IOException {
 return CharStreams.toString(new InputStreamReader(
 is, UTF_8));
 }
 }
 static class StreamApi implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 return new BufferedReader(new InputStreamReader(inputStream))
 .lines().collect(Collectors.joining("\n"));
 }
 }
 static class ParallelStreamApi implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 return new BufferedReader(new InputStreamReader(inputStream)).lines()
 .parallel().collect(Collectors.joining("\n"));
 }
 }
 static class ByteArrayOutputStreamTest implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 try(ByteArrayOutputStream result = new ByteArrayOutputStream()) {
 byte[] buffer = new byte[1024];
 int length;
 while ((length = inputStream.read(buffer)) != -1) {
 result.write(buffer, 0, length);
 }
 return result.toString(UTF_8);
 }
 }
 }
 static class BufferReaderTest implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 String newLine = System.getProperty("line.separator");
 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
 StringBuilder result = new StringBuilder(UTF_8);
 String line;
 boolean flag = false;
 while ((line = reader.readLine()) != null) {
 result.append(flag ? newLine : "").append(line);
 flag = true;
 }
 return result.toString();
 }
 }
 static class BufferedInputStreamVsByteArrayOutputStream implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 BufferedInputStream bis = new BufferedInputStream(inputStream);
 ByteArrayOutputStream buf = new ByteArrayOutputStream();
 int result = bis.read();
 while (result != -1) {
 buf.write((byte) result);
 result = bis.read();
 }
 return buf.toString(UTF_8);
 }
 }
 static class InputStreamAndStringBuilder implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 int ch;
 StringBuilder sb = new StringBuilder(UTF_8);
 while ((ch = inputStream.read()) != -1)
 sb.append((char) ch);
 return sb.toString();
 }
 }
 static class Java9ISTransferTo implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 ByteArrayOutputStream bos = new ByteArrayOutputStream();
 inputStream.transferTo(bos);
 return bos.toString(UTF_8);
 }
 }
 static class Java9ISReadAllBytes implements Stringify {
 @Override
 public String inputStreamToString(InputStream inputStream) throws IOException {
 return new String(inputStream.readAllBytes(), UTF_8);
 }
 }
}
Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered Feb 13, 2018 at 21:30
13
  • Making benchmarks in Java is not easy (especially because of JIT). After reading Benchmark source code, I'm convinced that those values above are not precise and everyone should be careful by believing them. Commented May 16, 2019 at 22:08
  • @Dalibor you probably should provide more reasoning for your claim rather than just a link. Commented May 28, 2019 at 14:06
  • I think that it is really known fact that it is not easy to make your own benchmark. For those who do not know that, there is link ;) Commented May 29, 2019 at 22:04
  • @Dalibor I am perhaps not the best, but I have a good understanding of Java benchmarks, so unless you can point out a specific problem, you are just misleading, and I will not continue the conversation with you under those conditions. Commented May 29, 2019 at 23:56
  • 4
    From the accepted answer: Rule 0: Read the paper, which essentially warns against attempting a micro-benchmark. Rule 1: You have no warm up phase. Rule 2-3: You've given no indication you used these flags. Rule 8: Use a library like JMH. With 135 votes in the comments: Don't use System.currentTimeMillis(). Moving on to other highly voted answers. Jon Skeet: use System.gc() between iterations, and run your test long enough to measure the results in seconds, not milliseconds. Mixing tests in a single JVM run is bad, as the compiler optimizations done for one test will impact another. Commented Nov 15, 2019 at 21:55
44

I'd use some Java 8 tricks.

public static String streamToString(final InputStream inputStream) throws Exception {
 // buffering optional
 try
 (
 final BufferedReader br
 = new BufferedReader(new InputStreamReader(inputStream))
 ) {
 // parallel optional
 return br.lines().parallel().collect(Collectors.joining("\n"));
 } catch (final IOException e) {
 throw new RuntimeException(e);
 // whatever.
 }
}

Essentially the same as some other answers except more succinct.

Ian2thedv
2,7012 gold badges28 silver badges47 bronze badges
answered Jul 17, 2014 at 17:58
0
40

Pure Java solution using Streams, works since Java 8.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
// ...
public static String inputStreamToString(InputStream is) throws IOException {
 try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
 return br.lines().collect(Collectors.joining(System.lineSeparator()));
 }
}

As mentioned by Christoffer Hammarström below other answer it is safer to explicitly specify the Charset. I.e. The InputStreamReader constructor can be changes as follows:

new InputStreamReader(is, Charset.forName("UTF-8"))
answered Feb 26, 2015 at 18:39
1
  • I would put System.lineSeparator() into a constant. Commented Apr 4 at 1:15
40

I ran some timing tests because time matters, always.

I attempted to get the response into a String 3 different ways. (shown below)
I left out try/catch blocks for the sake readability.

To give context, this is the preceding code for all 3 approaches:

 String response;
 String url = "www.blah.com/path?key=value";
 GetMethod method = new GetMethod(url);
 int status = client.executeMethod(method);

1)

 response = method.getResponseBodyAsString();

2)

InputStream resp = method.getResponseBodyAsStream();
InputStreamReader is=new InputStreamReader(resp);
BufferedReader br=new BufferedReader(is);
String read = null;
StringBuffer sb = new StringBuffer();
while((read = br.readLine()) != null) {
 sb.append(read);
}
response = sb.toString();

3)

InputStream iStream = method.getResponseBodyAsStream();
StringWriter writer = new StringWriter();
IOUtils.copy(iStream, writer, "UTF-8");
response = writer.toString();

So, after running 500 tests on each approach with the same request/response data, here are the numbers. Once again, these are my findings and your findings may not be exactly the same, but I wrote this to give some indication to others of the efficiency differences of these approaches.

Ranks:
Approach #1
Approach #3 - 2.6% slower than #1
Approach #2 - 4.3% slower than #1

Any of these approaches is an appropriate solution for grabbing a response and creating a String from it.

martijnn2008
3,6505 gold badges32 silver badges42 bronze badges
answered Oct 12, 2011 at 17:23
0
31

Here's more-or-less sampath's answer, cleaned up a bit and represented as a function:

String streamToString(InputStream in) throws IOException {
 StringBuilder out = new StringBuilder();
 BufferedReader br = new BufferedReader(new InputStreamReader(in));
 for (String line = br.readLine(); line != null; line = br.readLine())
 out.append(line);
 br.close();
 return out.toString();
}
Dmitriy Popov
2,3703 gold badges29 silver badges40 bronze badges
answered Mar 30, 2012 at 19:52
1
  • br.close() has to be done within a finally or ` try-with-resources` block. Commented Jul 5, 2023 at 10:26
30

If you were feeling adventurous, you could mix Scala and Java and end up with this:

scala.io.Source.fromInputStream(is).mkString("")

Mixing Java and Scala code and libraries has it's benefits.

See full description here: Idiomatic way to convert an InputStream to a String in Scala

answered Mar 7, 2012 at 7:32
0
30

If you can't use Commons IO (FileUtils, IOUtils, and CopyUtils), here's an example using a BufferedReader to read the file line by line:

public class StringFromFile {
 public static void main(String[] args) /*throws UnsupportedEncodingException*/ {
 InputStream is = StringFromFile.class.getResourceAsStream("file.txt");
 BufferedReader br = new BufferedReader(new InputStreamReader(is/*, "UTF-8"*/));
 final int CHARS_PER_PAGE = 5000; //counting spaces
 StringBuilder builder = new StringBuilder(CHARS_PER_PAGE);
 try {
 for(String line=br.readLine(); line!=null; line=br.readLine()) {
 builder.append(line);
 builder.append('\n');
 }
 }
 catch (IOException ignore) { }
 String text = builder.toString();
 System.out.println(text);
 }
}

Or if you want raw speed, I'd propose a variation on what Paul de Vrieze suggested (which avoids using a StringWriter (which uses a StringBuffer internally):

public class StringFromFileFast {
 public static void main(String[] args) /*throws UnsupportedEncodingException*/ {
 InputStream is = StringFromFileFast.class.getResourceAsStream("file.txt");
 InputStreamReader input = new InputStreamReader(is/*, "UTF-8"*/);
 final int CHARS_PER_PAGE = 5000; //counting spaces
 final char[] buffer = new char[CHARS_PER_PAGE];
 StringBuilder output = new StringBuilder(CHARS_PER_PAGE);
 try {
 for(int read = input.read(buffer, 0, buffer.length);
 read != -1;
 read = input.read(buffer, 0, buffer.length)) {
 output.append(buffer, 0, read);
 }
 } catch (IOException ignore) { }
 String text = output.toString();
 System.out.println(text);
 }
}
Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered May 18, 2010 at 12:57
0
25

Use the java.io.InputStream.transferTo(OutputStream) supported in Java 9 and the ByteArrayOutputStream.toString(String) which takes the charset name:

public static String gobble(InputStream in, String charsetName) throws IOException {
 ByteArrayOutputStream bos = new ByteArrayOutputStream();
 in.transferTo(bos);
 return bos.toString(charsetName);
}
answered Jan 28, 2016 at 15:55
0
24

This one is nice because:

  • It safely handles the Charset.
  • You control the read buffer size.
  • You can provision the length of the builder and it doesn't have to be an exact value.
  • Is free from library dependencies.
  • Is for Java 7 or higher.

How to do it

public static String convertStreamToString(InputStream is) throws IOException {
 StringBuilder sb = new StringBuilder(2048); // Define a size if you have an idea of it.
 char[] read = new char[128]; // Your buffer size.
 try (InputStreamReader ir = new InputStreamReader(is, StandardCharsets.UTF_8)) {
 for (int i; -1 != (i = ir.read(read)); sb.append(read, 0, i));
 }
 return sb.toString();
}

For JDK 9

public static String inputStreamString(InputStream inputStream) throws IOException {
 try (inputStream) {
 return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
 }
}
Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered Jun 8, 2014 at 7:46
0
24

This is an answer adapted from org.apache.commons.io.IOUtils source code, for those who want to have the Apache implementation, but do not want the whole library.

private static final int BUFFER_SIZE = 4 * 1024;
public static String inputStreamToString(InputStream inputStream, String charsetName)
 throws IOException {
 StringBuilder builder = new StringBuilder();
 InputStreamReader reader = new InputStreamReader(inputStream, charsetName);
 char[] buffer = new char[BUFFER_SIZE];
 int length;
 while ((length = reader.read(buffer)) != -1) {
 builder.append(buffer, 0, length);
 }
 return builder.toString();
}
Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered Aug 3, 2014 at 9:47
0
22
String inputStreamToString(InputStream inputStream, Charset charset) throws IOException {
 try (
 final StringWriter writer = new StringWriter();
 final InputStreamReader reader = new InputStreamReader(inputStream, charset)
 ) {
 reader.transferTo(writer);
 return writer.toString();
 }
}
answered Apr 5, 2020 at 0:03
22

Make sure to close the streams at the end if you use Stream Readers

private String readStream(InputStream iStream) throws IOException {
 // Build a Stream Reader, it can read character by character
 InputStreamReader iStreamReader = new InputStreamReader(iStream);
 // Build a buffered Reader, so that I can read whole line at once
 BufferedReader bReader = new BufferedReader(iStreamReader);
 String line = null;
 StringBuilder builder = new StringBuilder();
 while((line = bReader.readLine()) != null) { // Read till end
 builder.append(line);
 builder.append("\n"); // Append new line to preserve lines
 }
 bReader.close(); // Close all opened stuff
 iStreamReader.close();
 //iStream.close(); // Let the creator of the stream close it!
 // some readers may auto close the inner stream
 return builder.toString();
}

On JDK 7+, you can use try-with-resources construct.

/**
 * Reads the stream into a string
 * @param iStream the input stream
 * @return the string read from the stream
 * @throws IOException when an IO error occurs
 */
private String readStream(InputStream iStream) throws IOException {
 // Buffered reader allows us to read line by line
 try (BufferedReader bReader =
 new BufferedReader(new InputStreamReader(iStream))) {
 StringBuilder builder = new StringBuilder();
 String line;
 while((line = bReader.readLine()) != null) { // Read till end
 builder.append(line);
 builder.append("\n"); // Append new line to preserve lines
 }
 return builder.toString();
 }
}
Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered Nov 17, 2012 at 12:39
0
17

Here is the complete method for converting InputStream into String without using any third party library. Use StringBuilder for single threaded environment otherwise use StringBuffer.

public static String getString( InputStream is) throws IOException {
 int ch;
 StringBuilder sb = new StringBuilder();
 while((ch = is.read()) != -1)
 sb.append((char)ch);
 return sb.toString();
}
rtruszk
3,92213 gold badges39 silver badges53 bronze badges
answered Apr 9, 2014 at 10:37
0
17

Another one, for all the Spring users:

import java.nio.charset.StandardCharsets;
import org.springframework.util.FileCopyUtils;
public String convertStreamToString(InputStream is) throws IOException { 
 return new String(FileCopyUtils.copyToByteArray(is), StandardCharsets.UTF_8);
}

The utility methods in org.springframework.util.StreamUtils are similar to the ones in FileCopyUtils, but they leave the stream open when done.

answered Jul 29, 2016 at 20:58
0
17

Kotlin users simply do:

println(InputStreamReader(is).readText())

whereas

readText()

is the Kotlin standard library’s built-in extension method.

Peter Mortensen
31.6k22 gold badges110 silver badges134 bronze badges
answered Feb 4, 2015 at 1:12
1
  • You can now do: is.reader().readText() Commented May 2, 2024 at 14:35
15

Here's how to do it using just the JDK using byte array buffers. This is actually how the commons-io IOUtils.copy() methods all work. You can replace byte[] with char[] if you're copying from a Reader instead of an InputStream.

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
...
InputStream is = ....
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
byte[] buffer = new byte[8192];
int count = 0;
try {
 while ((count = is.read(buffer)) != -1) {
 baos.write(buffer, 0, count);
 }
}
finally {
 try {
 is.close();
 }
 catch (Exception ignore) {
 }
}
String charset = "UTF-8";
String inputStreamAsString = baos.toString(charset);
Matt
6373 silver badges10 bronze badges
answered Nov 2, 2012 at 12:37
0
10

The easiest way in JDK is with the following code snippets.

String convertToString(InputStream in) {
 String resource = new Scanner(in).useDelimiter("\\Z").next();
 return resource;
}
Dmitriy Popov
2,3703 gold badges29 silver badges40 bronze badges
answered Aug 9, 2016 at 20:18
2
  • Why is it "\\Z"? Commented Nov 15, 2023 at 2:35
  • An explanation would be in order. E.g., what is the idea/gist? From the Help Center: "...always explain why the solution you're presenting is appropriate and how it works". Please respond by editing (changing) your answer, not here in comments (*** *** *** *** *** *** *** *** *** *** *** without *** *** *** *** *** *** *** *** *** *** *** "Edit:", "Update:", or similar - the answer should appear as if it was written today). Commented Nov 15, 2023 at 2:35
9

In terms of reduce, and concat it can be expressed in Java 8 as:

String fromFile = new BufferedReader(new 
InputStreamReader(inputStream)).lines().reduce(String::concat).get();
Derlin
9,9112 gold badges34 silver badges57 bronze badges
answered Jan 21, 2016 at 14:28
0
8

Here's my Java 8 based solution, which uses the new Stream API to collect all lines from an InputStream:

public static String toString(InputStream inputStream) {
 BufferedReader reader = new BufferedReader(
 new InputStreamReader(inputStream));
 return reader.lines().collect(Collectors.joining(
 System.getProperty("line.separator")));
}
answered Sep 2, 2015 at 11:19
0
1
2 3

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.