2010-10-27 4 views
6

Я хочу, чтобы читал большой InputStream и возвращал его как строку. Этот InputStream является большим. Таким образом, обычно это занимает много времени и много памяти, в то время как оно возбуждает. Следующий код - тот, который я разработал до сих пор. Мне нужно преобразовать этот код, так как он выполняет задание в меньшей степени, занимая меньше памяти.Настройка производительности чтения большого InputStream в java

Можете ли вы дать мне какое-либо представление об этом.

BufferedReader br = 
    new BufferedReader(
     new InputStreamReader(
      connection.getInputStream(), 
      "UTF-8") 
     ); 

StringBuilder response = new StringBuilder(1000); 

char[] buffer = new char[4096]; 

int n = 0; 
while(n >= 0){ 
    n = br.read(buffer, 0, buffer.length); 
    if(n > 0){ 
     response.append(buffer, 0, n); 
    } 
} 
return response.toString(); 

Спасибо!

+2

Что такое «много» памяти. Неизбежно, что вам понадобится достаточно памяти, чтобы удерживать всю строну, которую вы создаете. Вы видите что-то значительно хуже, чем вы ожидали? – djna

+0

что ты читаешь? – dogbane

+0

Да. это правда, что потребляемая память пропорциональна размеру ответа (String). Но здесь он собирается эффективно использовать память (уменьшая ненужное использование памяти и т. Д.). Например, я использовал StringBuilder вместо добавления ввода в ту же строку, используя + (например, str = str + newStr), чтобы уменьшить ненужное использование памяти. Таким образом, я ожидал дальнейших идей, чтобы сделать мой код намного лучше, управляя памятью и ускоряя код. – Namalak

ответ

3

Когда вы выполняете буферизованный ввод-вывод, вы можете просто читать один символ за раз из буферизованного считывателя. Затем создайте строку и сделайте toString() в конце.

+0

Разве это не символы чтения, а хранение их в массиве символов лучше, чем чтение каждого символа и buildUp строку? Я имею в виду read() Vs read (char [], int start, int end) – Namalak

+1

Это то, что делает буферизованный читатель под обложками ... Попробуйте посмотреть на источник BufferedReader. –

1

Возможно, вы обнаружите, что для больших файлов в некоторых операционных системах mmap в файле через FileChannel.map даст вам лучшую производительность - скопируйте файл и создайте строку из сопоставленного ByteBuffer. Однако вам придется ориентироваться, так как может случиться так, что в некоторых случаях «традиционный» IO быстрее.

+0

ОП считывает URL-адрес, а не файл. – dogbane

+0

Да. Я новичок в этом FileChannel.map. Можно ли это использовать с OP, который читает URL-адрес – Namalak

+0

@dogbane и Namalak: чтобы быть справедливым, это не было ясно, пока я не оставил свой ответ :) Я оставлю это здесь, если кто-то придет позже и захочет сделать то же самое для файла. –

0

Знаете ли вы заранее, насколько вероятно максимальная длина вашей строки? В настоящее время вы указываете интуитивную емкость 1000 для вашего буфера. Если то, что вы читаете, намного больше, чем вы заплатите некоторую стоимость при распределении больших внутренних буферов.

Если у вас есть контроль над жизненным циклом того, что вы читаете, возможно, вы могли бы выделить один повторно используемый байтовый массив в качестве буфера. Следовательно, избегая сбора мусора.

0

Увеличьте размер вашего буфера. Чем больше буфер, тем быстрее все данные могут быть прочитаны. Если вы знаете (или можете работать), сколько байтов доступно в потоке, вы даже можете выделить буфер с одинаковым размером вверх.

+0

Спасибо. 1000 хорош до сих пор. Неоправданно увеличение размера буфера также неэффективно, не так ли? – Namalak

+0

Я имел в виду буфер символов, который вы установили в 4096. – dogbane

0

Вы можете запустить код в отдельном потоке ... он не будет работать быстрее, но, по крайней мере, ваша программа сможет выполнять какую-то другую работу, а не ждать данных из потока.

+0

Но нет никаких параллельных исполняемых файлов. – Namalak