¿Cómo es la mejor manera de extraer todo el contenido de un objeto BufferedReader en Java?

StackOverflow https://stackoverflow.com/questions/3918720

Pregunta

Estoy tratando de obtener una página web completa a través de un URLConnection.

¿Cuál es la forma más eficiente de hacer esto?

Estoy haciendo esto ya:

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 tiene toda la página HTML.

¿Fue útil?

Solución

Su enfoque se ve muy bien, sin embargo, puede que sea un poco más eficiente, evitando la creación de objetos String intermedios para cada línea.

La forma de hacer esto es leer directamente en un char temporal [] buffer.

Esta es una versión ligeramente modificada de su código que hace esto (menos toda la comprobación de errores, manejo de excepciones, etc., para mayor claridad):

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

Para obtener un rendimiento aún más, por supuesto puede hacer pequeñas cosas adicionales como pre-asignación de la matriz de caracteres y StringBuffer si este código se va a llamar con frecuencia.

Otros consejos

creo que este es de la mejor manera. El tamaño de la página es fija ( "es lo que es"), por lo que no se puede mejorar la memoria. Tal vez usted puede comprimir el contenido una vez que los tiene, pero no son muy útiles en esa forma. Me imagino que con el tiempo que usted quiere analizar el HTML en un árbol DOM.

Cualquier cosa que haga para paralelizar la lectura sería excesivamente complicar la solución.

Me gustaría recomendar el uso de un StringBuilder con un tamaño predeterminado de 2048 o 4096.

¿Por qué piensan que el código que envió no es suficiente? Parece como si es culpable de la optimización prematura.

Ejecutar con lo que tienes y dormir por la noche.

¿Qué desea hacer con el código HTML obtenido? Analizarlo? Puede ser bueno saber que un analizador poco decente HTML ya puede tener un argumento del constructor o método que lleva directamente un URL o InputStream de manera que usted no necesita preocuparse de funcionamiento que fluye por el estilo.

Si se asume que todo lo que quiere hacer se describe en su anterior pregunta , por ejemplo Jsoup se podía obtener todos los enlaces de noticias extraordinaria fácil como sigue:

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

Esto produce la siguiente después de sólo unos segundos:

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

¿Alguien ya dijo que la expresión regular es absolutamente la herramienta equivocada para analizar HTML? ;)

Ver también:

Se puede tratar de usar commons-io de Apache (http://commons.apache.org/io/api-release/org/apache/commons/io/IOUtils.html)

new String(IOUtils.toCharArray(connection.getInputStream()))

Hay algunas consideraciones técnicas. Es posible que desee utilizar en lugar de HttpURLConnection URLConnection.

HttpURLConnection soportes Codificación de transferencia fragmentada, lo que le permite procesar los datos en trozos, en lugar de amortiguar todo el contenido antes de empezar a hacer el trabajo. Esto puede conducir a una experiencia de usuario mejorada.

Además, HttpURLConnection soporta conexiones persistentes. ¿Por qué cerrar esa conexión si vas a solicitar un recurso más inmediato? Mantener la conexión TCP abierta con el servidor web permite que la aplicación rápida descargar varios recursos sin tener que gastar la sobrecarga (latencia) de establecer una nueva conexión TCP para cada recurso.

indicar al servidor que usted apoya gzip y envolver un BufferedReader alrededor GZIPInputStream si la cabecera de respuesta dice que el contenido se comprime.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top