2009-09-04 6 views

Répondre

30

Une erreur extrêmement courante est l'échec de la conversion d'une réponse HTTP d'octets en caractères. Pour ce faire, vous devez connaître le codage de caractères de la réponse. Heureusement, ceci est spécifié en tant que paramètre dans le paramètre "Content-Type". Mais le mettre dans le corps lui-même, comme un attribut "http-equiv" dans un tag meta est également une option. Donc, il est étonnamment compliqué de charger une page dans un String correctement, et même les bibliothèques tierces comme HttpClient n'offrent pas de solution générale.

Voici une implémentation simple qui traitera le cas le plus courant:

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

Je sais que c'est une question vraiment ancienne, mais si vous pouviez vérifier http://stackoverflow.com/questions/7615014/encoding-issues-crawling-i18n-websites je l'apprécierais vraiment. – dimo414

+0

Veuillez changer le codage par défaut en "UTF-8" (http://trends.builtwith.com/encoding). Les gens apprennent de votre (très bonne) réponse! –

+4

@TalWeiss La popularité n'a pas d'importance; ISO-8859-1 est [la valeur par défaut spécifiée.] (Http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1). "Si aucun paramètre de charset explicite n'est fourni par l'expéditeur, les sous-types de support du type" text "sont définis pour avoir une valeur de charset par défaut de" ISO-8859-1 "lorsqu'ils sont reçus via HTTP. 8859-1 'ou ses sous-ensembles DOIT être étiqueté avec une valeur charset appropriée. " – erickson

1

J'utilise ceci:

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

Il fonctionne la plupart du temps.

+0

Il y aura un supplément « \ n » au fin de la chaîne résultante. –

4

Vous pouvez simplifier encore un peu en utilisant 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); 
Questions connexes