36

I want to optimize this code:

InputStream is = rp.getEntity().getContent();      

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

String text = "";
String aux = "";

while ((aux = reader.readLine()) != null) {
        text += aux;
      }

The thing is that i don't know how to read the content of the bufferedreader and copy it in a String faster than what I have above. I need to spend as little time as possible. Thank you

Cata
  • 11,133
  • 11
  • 65
  • 86
  • 1
    You could use a StringBuilder for starters. It will avoid the concatenation of Strings. You could also use the read method with a large char array but getting the optimal array size will require some benchmarking. – James P. Jan 12 '11 at 08:48
  • 5
    Are you sure you don't need to put back the linefeed codes that readLine() takes out? – Thilo Jan 12 '11 at 08:55
  • LOL for "I need to spend as little time as possible". I assume that this means that it needs to be as efficient as possible, but I read it as "I want to do as little work as possible to achieve the optimal result." – jwir3 Oct 16 '14 at 16:34
  • Also see: http://stackoverflow.com/questions/2980805/string-assembly-by-stringbuilder-vs-stringwriter-and-printwriter – Christophe Roussy Dec 09 '15 at 10:26

6 Answers6

85

Using string concatenation in a loop is the classic performance killer (because Strings are immutable, the entire, increasingly large String is copied for each concatenation). Do this instead:

StringBuilder builder = new StringBuilder();
String aux = "";

while ((aux = reader.readLine()) != null) {
    builder.append(aux);
}

String text = builder.toString();
Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • 4
    That's assuming java 1.5 or later. Otherwise it would be StringBuffer you would use. – Greg McGowan Jan 12 '11 at 08:49
  • It's a good idea, until I don't have other alternatives I will try StringBuffer. – Cata Jan 12 '11 at 08:59
  • 9
    Worth pointing out that readLine consumes newlines. This loop won't be very useful unless you want to turn all the text into one line (with no sperator where the newlines used to be) – Peter Lawrey Jan 12 '11 at 09:01
  • 6
    @Greg: even Java 5 passed its EOSL date over a year ago. It's time to stop wasting mental capacity on issues concering even older versions. – Michael Borgwardt Jan 12 '11 at 09:09
  • That may be true but I was simply stating that you are assuming Cata can use java 1.5. – Greg McGowan Jan 12 '11 at 09:16
  • 3
    @Greg: and I am stating that this is an assumption that, in this day and age, everyone should make without hesitation unless there is explicit information contradicting it. – Michael Borgwardt Jan 12 '11 at 09:55
  • 2
    Given that Java 1.5 is end of support, and Java 1.6 is end of life, it is safe to assume that your compiler is Java 1.6, or 1.7 (maybe 1.5) but very unlikely to be 1.4 or prior. I would say it is VERY safe to use StringBuilder. – Armand Jun 10 '13 at 17:22
26

You can try Apache IOUtils.toString. This is what they do:

StringWriter sw = new StringWriter();
char[] buffer = new char[1024 * 4];
int n = 0;
while (-1 != (n = input.read(buffer))) {
    sw.write(buffer, 0, n);
}
String text = sw.toString();
dogbane
  • 266,786
  • 75
  • 396
  • 414
  • 1
    Needs more upvotes, probably better than reading line by line, especially if the lines are short. See http://stackoverflow.com/questions/2980805/string-assembly-by-stringbuilder-vs-stringwriter-and-printwriter – Christophe Roussy Dec 09 '15 at 10:20
7

When BufferedReader reads from Socket, it is necessary to add bufferedReader.ready():

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

StringBuilder sb= new StringBuilder();
String line = "";

while (br.ready() && (line = br.readLine()) != null) {
    sb.append(line + "\r\n");
}

String result = sb.toString();
mjaggard
  • 2,389
  • 1
  • 23
  • 45
michalv
  • 365
  • 3
  • 17
1

One line solution:

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

Imports:

import java.io.*;
import static java.lang.System.lineSeparator;
import static java.util.stream.Collectors.joining;
Hykilpikonna
  • 1,749
  • 2
  • 15
  • 32
0

I wrote a simple function to do this using StringBuilder and While loop with catching IOException inside.

public String getString(BufferedReader bufferedReader) {
    StringBuilder stringBuilder = new StringBuilder();
    String line = null;

    do {
        try {
            if ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line).append(System.lineSeparator());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    } while (line != null);

    return stringBuilder.toString();
}
Thach Van
  • 1,381
  • 16
  • 19
-1

You can use StringBuffer

while ((aux = reader.readLine()) != null) {
     stringBuffer.append(aux);
}