Как это лучший способ, чтобы извлечь все содержимое из объекта командой bufferedreader в Java?
Я пытаюсь получить всю веб-страницу через URLConnection.
Какой самый эффективный способ сделать это?
Я уже делаю это:
URL url = new URL("http://www.google.com/");
URLConnection connection;
connection = url.openConnection();
InputStream in = connection.getInputStream();
BufferedReader bf = new BufferedReader(new InputStreamReader(in));
StringBuffer html = new StringBuffer();
String line = bf.readLine();
while(line!=null){
html.append(line);
line = bf.readLine();
}
bf.close();
Html содержит всю HTML-страницу.
5 ответов:
Ваш подход выглядит довольно хорошо, однако вы можете сделать его несколько более эффективным, избегая создания промежуточных строковых объектов для каждой строки.
Способ сделать это-прочитать непосредственно во временный буфер char [].
Вот немного измененная версия вашего кода, которая делает это (минус вся проверка ошибок, обработка исключений и т. д. для ясности):
URL url = new URL("http://www.google.com/"); URLConnection connection; connection = url.openConnection(); InputStream in = connection.getInputStream(); BufferedReader bf = new BufferedReader(new InputStreamReader(in)); StringBuffer html = new StringBuffer(); char[] charBuffer = new char[4096]; int count=0; do { count=bf.read(charBuffer, 0, 4096); if (count>=0) html.append(charBuffer,0,count); } while (count>0); bf.close();
Для еще большей производительности, вы, конечно, можете делать небольшие дополнительные вещи, такие как предварительное распределение массив символов и StringBuffer, если этот код будет вызываться часто.
Я думаю, что это лучший способ. Размер страницы фиксирован ("это то, что есть"), поэтому вы не можете улучшить память. Возможно, вы можете сжать содержимое, как только они у вас есть, но они не очень полезны в этой форме. Я бы предположил, что в конечном итоге вы захотите разобрать HTML в дерево DOM.
Все, что вы делаете для распараллеливания чтения, будет чрезмерно усложнять решение.
Я бы рекомендовал использовать StringBuilder с размером по умолчанию 2048 или 4096.
Почему вы думаете, что кода, который вы разместили, недостаточно? Вы говорите так, будто виноваты в преждевременной оптимизации.
Бегите с тем, что у вас есть, и спите по ночам.
Что вы хотите сделать с полученным HTML? Разобрать его? Это может быть полезно знать, что немного приличный HTML-парсер уже может иметь конструктор или аргумент метода, который принимает прямой
URL
илиInputStream
, так что вам не нужно беспокоиться о потоковой производительности, как это.Предполагая, что все, что вы хотите сделать, описано в вашем предыдущем вопросе , например Jsoup вы могли бы получить все эти новостные ссылки необычайно легко следующим образом:
Document document = Jsoup.connect("http://news.google.com.ar/nwshp?hl=es&tab=wn").get(); Elements newsLinks = document.select("h2.title a:eq(0)"); for (Element newsLink : newsLinks) { System.out.println(newsLink.attr("href")); }
Это всего через несколько секунд выдает следующее:
http://www.infobae.com/mundo/541259-100970-0-Pinera-confirmo-que-el-rescate-comenzara-las-20-y-durara-24-y-48-horas http://www.lagaceta.com.ar/nota/403112/Argentina/Boudou-disculpo-con-DAIA-pero-volvio-cuestionar-medios.html http://www.abc.es/agencias/noticia.asp?noticia=550415 http://www.google.com/hostednews/epa/article/ALeqM5i6x9rhP150KfqGJvwh56O-thi4VA?docId=1383133 http://www.abc.es/agencias/noticia.asp?noticia=550292 http://www.univision.com/contentroot/wirefeeds/noticias/8307387.shtml http://noticias.terra.com.ar/internacionales/ecuador-apoya-reclamo-argentino-por-ejercicios-en-malvinas,3361af2a712ab210VgnVCM4000009bf154d0RCRD.html http://www.infocielo.com/IC/Home/index.php?ver_nota=22642 http://www.larazon.com.ar/economia/Cristina-Fernandez-Censo-indispensable-pais_0_176100098.html http://www.infobae.com/finanzas/541254-101275-0-Energeticas-llevaron-la-Bolsa-portena-ganancias http://www.telam.com.ar/vernota.php?tipo=N&idPub=200661&id=381154&dis=1&sec=1 http://www.ambito.com/noticia.asp?id=547722 http://www.canal-ar.com.ar/noticias/noticiamuestra.asp?Id=9469 http://www.pagina12.com.ar/diario/cdigital/31-154760-2010-10-12.html http://www.lanacion.com.ar/nota.asp?nota_id=1314014 http://www.rpp.com.pe/2010-10-12-ganador-del-pulitzer-destaca-nobel-de-mvll-noticia_302221.html http://www.lanueva.com/hoy/nota/b44a7553a7/1/79481.html http://www.larazon.com.ar/show/sdf_0_176100096.html http://www.losandes.com.ar/notas/2010/10/12/batista-siento-comodo-dieron-respaldo-520595.asp http://deportes.terra.com.ar/futbol/los-rumores-empiezan-a-complicar-la-vida-de-river-y-vuelve-a-sonar-gallego,a24483b8702ab210VgnVCM20000099f154d0RCRD.html http://www.clarin.com/deportes/futbol/Exigieron-Roman-regreso-Huracan_0_352164993.html http://www.el-litoral.com.ar/leer_noticia.asp?idnoticia=146622 http://www.nuevodiarioweb.com.ar/nota/181453/Locales/C%C3%A1ncer_mama:_200_casos_a%C3%B1o_Santiago.html http://www.ultimahora.com/notas/367322-Funcionarios-sanitarios-capacitaran-sobre-cancer-de-mama http://www.lanueva.com/hoy/nota/65092f2044/1/79477.html http://www.infobae.com/policiales/541220-101275-0-Se-suspendio-la-declaracion-del-marido-Fernanda-Lemos http://www.clarin.com/sociedad/educacion/titulo_0_352164863.htmlНеужели кто-то уже сказал, что regex-это абсолютно неправильный инструмент для разбора HTML? ;)
См. также:
Вы можете попробовать использовать commons-io из apache (http://commons.apache.org/io/api-release/org/apache/commons/io/IOUtils.html)
new String(IOUtils.toCharArray(connection.getInputStream()))
Есть некоторые технические соображения. Вы можете использовать HTTPURLConnection вместо URLConnection.
HTTPURLConnection поддерживает кодирование передачи фрагментами, что позволяет обрабатывать данные фрагментами, а не буферизировать все содержимое перед началом работы. Это может привести к улучшению пользовательского опыта.Кроме того, HTTPURLConnection поддерживает постоянные соединения. Зачем закрывать это соединение, если вы собираетесь сразу же запросить другой ресурс? Хранящий TCP-соединение, открытое с веб-сервером, позволяет приложению быстро загружать несколько ресурсов, не тратя накладные расходы (задержки) на установку нового TCP-соединения для каждого ресурса.
Сообщите серверу, что вы поддерживаете gzip, и оберните BufferedReader вокруг GZIPInputStream, если заголовок ответа говорит, что содержимое сжато.