Чтение inputStream с использованием BufferedReader.readLine () выполняется слишком медленно - PullRequest
39 голосов
/ 08 апреля 2011

Я использую следующий код.

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

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

Но чтение строки 200 занимает более 12 секунд.

Пожалуйста, помогите

Ответы [ 2 ]

30 голосов
/ 08 апреля 2011

Я сильно подозреваю, что это из-за сетевого подключения или веб-сервера, с которым вы разговариваете - это не ошибка BufferedReader. Попробуйте измерить это:

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

Я думаю, вы обнаружите, что это почти в то же время, что и при разборе текста.

Обратите внимание, что вы также должны дать InputStreamReader подходящую кодировку - кодировка по умолчанию для платформы почти наверняка не , что вы должны использовать.

8 голосов
/ 08 апреля 2011

У меня есть более длинный тест, чтобы попробовать.На чтение каждой строки в среднем уходит 160 нс при добавлении ее в список (что, вероятно, будет тем, что вы хотели, так как удаление строк не очень полезно.

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();
}

печатает

Average time to read a line was 158 ns.

Если вы хотите построить StringBuilder, сохраняя символы новой строки, я бы предложил следующий подход.

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);
}

Все еще печатает

Average time to read a line was 159 ns.

В обоих случаях скорость ограниченаотправитель не получатель. Оптимизируя отправителя, я сократил время до 105 нс на линию.

...