41

I am using following code.

BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;

StringBuilder responseData = new StringBuilder();
while((line = in.readLine()) != null) {
    responseData.append(line);
}

But it is taking more than 12 sec to read 200 line.

Please help

Lohit
  • 891
  • 5
  • 14
  • 26
  • Did it occur to you that the client may as well be the one being slow? Or the network? – Ingo Apr 08 '11 at 12:01
  • 1
    What is `conn`? Is it faster if you read the `InputStream` directly (into a `byte[]` that you'll discard? – Joachim Sauer Apr 08 '11 at 12:01
  • 1
    What's it reading *from*? I will be astonished if the problem has anything to do with buffering as such. Are you reading across the network? Are you, e.g., getting data from a network connection where the last line doesn't have a line terminator, so that `readLine` is sat there waiting for something it can recognize as the end of the line? Or from something that really is sending data that slowly? – Gareth McCaughan Apr 08 '11 at 12:02
  • The problem is in while loop. I have measured the time – Lohit Apr 08 '11 at 12:14
  • 6
    you don't think it is worth considering the idea that the reading process cannot be faster than the writing process? You measured the time - sure, but it seems you are not able to interpret your measurements. It's like I measure the speed of a red car, and then insist that it's the red colour that makes it go that fast. – Ingo Apr 08 '11 at 12:29
  • Did you ever thought, that `in.readLine()` read content line by line, and new line is a delimiter and when you concat string line by line -> you lost all '\r\n' from original content? – msangel Oct 23 '12 at 22:30

2 Answers2

30

I strongly suspect that's because of the network connection or the web server you're talking to - it's not BufferedReader's fault. Try measuring this:

InputStream stream = conn.getInputStream();
byte[] buffer = new byte[1000];
// Start timing
while (stream.read(buffer) > 0)
{
}
// End timing

I think you'll find it's almost exactly the same time as when you're parsing the text.

Note that you should also give InputStreamReader an appropriate encoding - the platform default encoding is almost certainly not what you should be using.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Dear jon i have tested the time. The time is taking for while loop only – Lohit Apr 08 '11 at 12:13
  • 6
    @Shashi: yes, because that's where it's actually reading from the network. Unless those lines are enormous, this really won't be BufferedReader / InputStreamReader overhead. – Jon Skeet Apr 08 '11 at 12:37
9

I have a longer test to try. This takes an average of 160 ns to read each line as add it to a List (Which is likely to be what you intended as dropping the newlines is not very useful.

public static void main(String... args) throws IOException {
    final int runs = 5 * 1000 * 1000;

    final ServerSocket ss = new ServerSocket(0);
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Socket serverConn = ss.accept();
                String line = "Hello World!\n";
                BufferedWriter br = new BufferedWriter(new OutputStreamWriter(serverConn.getOutputStream()));
                for (int count = 0; count < runs; count++)
                    br.write(line);
                serverConn.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();

    Socket conn = new Socket("localhost", ss.getLocalPort());

    long start = System.nanoTime();
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String line;

    List<String> responseData = new ArrayList<String>();
    while ((line = in.readLine()) != null) {
        responseData.add(line);
    }
    long time = System.nanoTime() - start;
    System.out.println("Average time to read a line was " + time / runs + " ns.");
    conn.close();
    ss.close();
}

prints

Average time to read a line was 158 ns.

If you want to build a StringBuilder, keeping newlines I would suggets the following approach.

Reader r = new InputStreamReader(conn.getInputStream());
String line;

StringBuilder sb = new StringBuilder();
char[] chars = new char[4*1024];
int len;
while((len = r.read(chars))>=0) {
    sb.append(chars, 0, len);
}

Still prints

Average time to read a line was 159 ns.

In both cases, the speed is limited by the sender not the receiver. By optimising the sender, I got this timing down to 105 ns per line.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130