Я делаю HTTP-запрос на получение приложения для Android, которое я делаю.
Я использую DefaultHttpClient и использую HttpGet для выдачи запроса. Я получаю ответ сущности и получаю объект InputStream для получения html страницы.
Затем я перебираю ответ, выполняя следующее:
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
String x = "";
x = r.readLine();
String total = "";
while(x!= null){
total += x;
x = r.readLine();
}
Однако это ужасно медленно.
Это неэффективно? Я не загружаю большую веб-страницу - www.cokezone.co.uk, поэтому размер файла не большой. Есть лучший способ сделать это?
Спасибо
Энди
Ответы:
Проблема в вашем коде заключается в том, что он создает множество тяжелых
String
объектов, копирует их содержимое и выполняет над ними операции. Вместо этого вы должны использовать,StringBuilder
чтобы избежать создания новыхString
объектов в каждом добавлении и чтобы избежать копирования массивов символов. Реализация для вашего случая будет примерно такой:Теперь вы можете использовать его
total
без преобразованияString
, но если вам нужен результат какString
, просто добавьте:String result = total.toString ();
Я постараюсь объяснить это лучше ...
a += b
(илиa = a + b
), гдеa
иb
являются строками, копирует содержимое обоихa
иb
в новый объект (обратите внимание, что вы также копируетеa
, который содержит накопленныйString
), и вы делаете эти копии на каждой итерации.a.append(b)
, гдеa
aStringBuilder
, напрямую добавляетb
содержимоеa
, чтобы вы не копировали накопленную строку на каждой итерации.источник
StringBuilder total = new StringBuilder(inputStream.available());
readline
цикла просто смешно. Эта модель должна была умереть с зеленым горошком в 70-х годах.Вы пробовали встроенный метод для преобразования потока в строку? Это часть библиотеки Apache Commons (org.apache.commons.io.IOUtils).
Тогда ваш код будет такой одной строкой:
Документация для этого может быть найдена здесь: http://commons.apache.org/io/api-1.4/org/apache/commons/io/IOUtils.html#toString%28java.io.InputStream%29
Библиотеку Apache Commons IO можно скачать здесь: http://commons.apache.org/io/download_io.cgi
источник
Еще одна возможность с гуавой:
зависимость:
compile 'com.google.guava:guava:11.0.2'
источник
Я считаю, что это достаточно эффективно ... Чтобы получить строку из InputStream, я бы вызвал следующий метод:
Я всегда использую UTF-8. Конечно, вы могли бы установить charset в качестве аргумента, кроме InputStream.
источник
Как насчет этого. Кажется, чтобы дать лучшую производительность.
Изменить: На самом деле этот вид охватывает как Steelbytes и Мориса Перри
источник
Возможно, несколько быстрее, чем ответ Хайме Сориано, и без проблем многобайтового кодирования ответа Адриана, я предлагаю:
источник
Возможно, вместо этого читайте «по одной строке за раз» и соединяйте строки, попробуйте «прочитать все доступные», чтобы избежать сканирования конца строки, а также избежать объединения строк.
то есть
InputStream.available()
иInputStream.read(byte[] b), int offset, int length)
источник
Чтение одной строки текста за раз и добавление указанной строки к строке по отдельности отнимает много времени как при извлечении каждой строки, так и при обработке большого количества вызовов метода.
Я смог добиться лучшей производительности, выделив байтовый массив приличного размера для хранения потоковых данных, который при необходимости итеративно заменяется большим массивом, и пытался прочитать столько, сколько мог вместить массив.
По какой-то причине Android неоднократно не загружал весь файл, когда код использовал InputStream, возвращаемый HTTPUrlConnection, поэтому мне пришлось прибегнуть к использованию как BufferedReader, так и механизма тайм-аута, созданного вручную, чтобы убедиться, что я получу весь файл или откажусь перевод.
EDIT: Получается, что если вам не нужно иметь содержание повторно кодированным (то есть, вы хотите содержание AS IS ) , вы не должны использовать любого из подклассов Reader. Просто используйте соответствующий подкласс Stream.
Замените начало предыдущего метода соответствующими строками следующего, чтобы ускорить его еще от 2 до 3 раз .
источник
Если файл длинный, вы можете оптимизировать свой код, добавив StringBuilder вместо использования конкатенации строк для каждой строки.
источник
источник
Для преобразования InputStream в String мы используем метод BufferedReader.readLine () . Мы выполняем итерацию до тех пор, пока BufferedReader не возвратит ноль, что означает, что больше нет данных для чтения. Каждая строка добавляется в StringBuilder и возвращается как String.
И, наконец, из любого класса, в который вы хотите конвертировать вызов функции
полный
источник
Я использую, чтобы прочитать полные данные:
источник