2009-09-04 11 views

risposta

30

Un errore estremamente comune è l'incapacità di convertire correttamente una risposta HTTP da byte a caratteri. Per fare ciò, devi conoscere la codifica dei caratteri della risposta. Si spera che questo sia specificato come parametro nel parametro "Content-Type". Ma inserirla nel corpo stesso, come attributo "http-equiv" in un tag meta è anche un'opzione.

Quindi, è sorprendentemente complicato caricare una pagina in un String correttamente e anche le librerie di terze parti come HttpClient non offrono una soluzione generale.

Ecco una semplice implementazione che gestirà il caso più comune:

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

So che questa è una domanda molto vecchia, ma se potessi controllare http://stackoverflow.com/questions/7615014/encoding-issues-crawling-i18n-websites lo apprezzerei molto. – dimo414

+0

Per favore cambia la codifica predefinita in "UTF-8" (http://trends.builtwith.com/encoding). Le persone stanno imparando dalla tua (molto buona) risposta! –

+4

@TalWeiss La popolarità non ha importanza; ISO-8859-1 è [l'impostazione predefinita specificata.] (Http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1). "Quando il mittente non fornisce alcun parametro charset esplicito, i sottotipi multimediali del tipo 'testo' sono definiti per avere un valore charset predefinito di 'ISO-8859-1' quando ricevuto via HTTP. Dati in set di caratteri diversi da 'ISO- 8859-1 'oi suoi sottoinsiemi DEVONO essere etichettati con un valore di set di caratteri appropriato. " – erickson

1

Io uso questo:

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

Funziona il più delle volte.

+0

Ci sarà un extra "\ n" al fine della stringa risultante. –

4

è ancora possibile semplificare un po 'con 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); 
Problemi correlati