2009-09-04 15 views

Respuesta

30

Un error extremadamente común es la falla al convertir correctamente una respuesta HTTP de bytes a caracteres. Para hacer esto, debes conocer la codificación de caracteres de la respuesta. Con suerte, esto se especifica como un parámetro en el parámetro "Content-Type". Pero ponerlo en el cuerpo mismo, como un atributo "http-equiv" en una etiqueta meta también es una opción.

Por lo tanto, es sorprendentemente complicado cargar una página en un String correctamente, e incluso las bibliotecas de terceros como HttpClient no ofrecen una solución general.

Aquí hay una aplicación sencilla que controlará el caso más común:

URL url = new URL("http://stackoverflow.com/questions/1381617"); 
URLConnection con = url.openConnection(); 
Pattern p = Pattern.compile("text/html;\\s+charset=([^\\s]+)\\s*"); 
Matcher m = p.matcher(con.getContentType()); 
/* If Content-Type doesn't match this pre-conception, choose default and 
* hope for the best. */ 
String charset = m.matches() ? m.group(1) : "ISO-8859-1"; 
Reader r = new InputStreamReader(con.getInputStream(), charset); 
StringBuilder buf = new StringBuilder(); 
while (true) { 
    int ch = r.read(); 
    if (ch < 0) 
    break; 
    buf.append((char) ch); 
} 
String str = buf.toString(); 
+0

Sé que esta es una pregunta muy antigua, pero si pudieran ver http://stackoverflow.com/questions/7615014/encoding-issues-crawling-i18n-websites, realmente lo agradecería. – dimo414

+0

Cambie la codificación predeterminada a "UTF-8" (http://trends.builtwith.com/encoding). ¡La gente está aprendiendo de tu (muy buena) respuesta! –

+4

@TalWeiss La popularidad no importa; ISO-8859-1 es [el predeterminado predeterminado.] (Http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1). "Cuando el remitente no proporciona ningún parámetro de juego de caracteres explícito, los subtipos de medios del tipo 'texto' se definen para que tengan un valor predeterminado de juego de caracteres 'ISO-8859-1' cuando se reciben por HTTP. Los datos en juegos de caracteres que no sean 'ISO- 8859-1 'o sus subconjuntos DEBEN etiquetarse con un valor de juego de caracteres apropiado. " – erickson

1

Yo uso este:

 BufferedReader bufferedReader = new BufferedReader( 
            new InputStreamReader( 
              new URL(urlToSeach) 
               .openConnection() 
               .getInputStream())); 

     StringBuilder sb = new StringBuilder(); 
     String line = null; 
     while((line = bufferedReader.readLine()) != null) { 
      sb.append(line) ; 
      sb.append("\n"); 
     } 
     .... in finally.... 
     buffer.close(); 

Es la mayor parte de las veces funciona.

+0

Habrá un extra "\ n" al fin de la cadena resultante. –

4

todavía puede simplificar un poco el uso de org.apache.commons.io.IOUtils:

URL url = new URL("http://stackoverflow.com/questions/1381617"); 
URLConnection con = url.openConnection(); 
Pattern p = Pattern.compile("text/html;\\s+charset=([^\\s]+)\\s*"); 
Matcher m = p.matcher(con.getContentType()); 
/* If Content-Type doesn't match this pre-conception, choose default and 
* hope for the best. */ 
String charset = m.matches() ? m.group(1) : "ISO-8859-1"; 
String str = IOUtils.toString(con.getInputStream(), charset); 
Cuestiones relacionadas