Lecture d'InputStream en UTF-8

96

J'essaie de lire un text/plainfichier sur Internet, ligne par ligne. Le code que j'ai en ce moment est:

URL url = new URL("http://kuehldesign.net/test.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
LinkedList<String> lines = new LinkedList();
String readLine;

while ((readLine = in.readLine()) != null) {
    lines.add(readLine);
}

for (String line : lines) {
    out.println("> " + line);
}

Le fichier,, test.txtcontient ¡Hélló!, que j'utilise pour tester l'encodage.

Quand j'examine le OutputStream( out), je le vois comme > ¬°H√©ll√≥!. Je ne crois pas que ce soit un problème avec le OutputStreamcar je peux me passer de out.println("é");problèmes.

Des idées pour lire le formulaire InputStreamcomme UTF-8? Merci!

Chris Kuehl
la source
1
Le protocole HTTP spécifie l'encodage. Pourquoi n'utilisez-vous pas une API de bibliothèque qui gère cela pour vous? Vous ne devriez jamais avoir à deviner l'encodage de cette manière. Je ne veux pas être négatif: vous allez très bien! Je me demande simplement s'il n'y a pas de moyen plus simple.
tchrist
1
Je n'aurai pas accès au serveur qui sert le text/plainfichier, malheureusement, et il n'utilise pas d'encodage UTF-8. Je n'étais pas au courant de bonnes bibliothèques réseau; Aucune suggestion?
Chris Kuehl
1
En regardant la documentation , je ne pense pas que vous deviez spécifier l'encodage du tout. Je suis surpris qu'ils vous donnent un flux d'octets! Vous avez accès à URLConnection sous- jacent , à partir de laquelle vous pouvez vérifier le Content-Encoding, puis ouvrir un InputStreamReader avec l'argument correct. Une vérification rapide de la source ne révèle rien qui semble faire cela pour vous, ce qui semble assez boiteux et sujet aux erreurs, donc j'ai probablement raté quelque chose.
tchrist

Réponses:

189

J'ai résolu mon propre problème. Cette ligne:

BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));

doit être:

BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));

ou depuis Java 7:

BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8));
Chris Kuehl
la source
3
Je suis presque sûr que cette forme du constructeur ne lèvera pas d'exception en cas d'entrée invalide. Vous devez utiliser le avec un CharsetDecoder decargument. C'est le même bogue de conception Java que les OutputStreamWriterconstructeurs ont: un seul des quatre condescend à vous dire quand quelque chose ne va pas. CharsetDecoder decLà encore, vous devez utiliser l' argument sophistiqué . La seule chose sûre et sensée à faire est de considérer tous les autres constructeurs comme obsolètes, car on ne peut pas leur faire confiance pour leur comportement.
tchrist
6
Depuis Java 7, il est possible d'écrire le fournir le jeu de caractères en tant que constante et non en tant que chaîneStandardCharsets.UTF_8
tobijdc
18
String file = "";

try {

    InputStream is = new FileInputStream(filename);
    String UTF8 = "utf8";
    int BUFFER_SIZE = 8192;

    BufferedReader br = new BufferedReader(new InputStreamReader(is,
            UTF8), BUFFER_SIZE);
    String str;
    while ((str = br.readLine()) != null) {
        file += str;
    }
} catch (Exception e) {

}

Essaye ça,.. :-)

Rohith
la source
8
Au lieu de file + = str, créez un StringBuilder et ajoutez-y. Le compilateur pourra peut-être optimiser l'ajout de la chaîne, mais cela crée probablement beaucoup de déchets
seand
2
Si vous voulez convertir un BufferedReader en une chaîne, utilisez Apache Commons, ne réinventez pas le wheal: String myStr = org.apache.commons.io.IOUtils.toString (myBufferedReaderInstance);
Jaime Marín
8
UTF8 = "utf8", belle variable;)
Nicofisi
7

J'ai rencontré le même problème chaque fois qu'il trouve qu'un caractère spécial le marque comme . pour résoudre cela, j'ai essayé d'utiliser l'encodage: ISO-8859-1

BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("txtPath"),"ISO-8859-1"));

while ((line = br.readLine()) != null) {

}

J'espère que cela peut aider tous ceux qui voient ce message.

Joshua Cleveland
la source
1
Pourriez-vous s'il vous plaît dire quels sont les caractères non pris en charge dans UTF-8?
USM