Lendo InputStream como UTF-8

96

Estou tentando ler um text/plainarquivo da Internet, linha por linha. O código que tenho agora é:

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

O arquivo test.txt,, contém ¡Hélló!, que estou usando para testar a codificação.

Quando reviso o OutputStream( out), vejo como > ¬°H√©ll√≥!. Não acredito que isso seja um problema com o, OutputStreamjá que posso fazer isso out.println("é");sem problemas.

Alguma idéia para ler o formato InputStreamUTF-8? Obrigado!

Chris Kuehl
fonte
1
O protocolo HTTP especifica a codificação. Por que você não está usando uma API de biblioteca que cuida disso para você? Você nunca deve ter que adivinhar a codificação dessa forma. Não quero ser negativo: você está indo muito bem! Eu só me pergunto se não existe uma maneira mais fácil.
cristão de
1
Não terei acesso ao servidor que está servindo o text/plainarquivo, infelizmente, e ele não está usando a codificação UTF-8. Eu não conhecia nenhuma boa biblioteca de rede; alguma sugestão?
Chris Kuehl
1
Olhando para os documentos , eu não acho que você teria que especificar a codificação. Estou surpreso que eles forneçam um fluxo de bytes! Você tem acesso ao URLConnection subjacente , a partir do qual pode verificar o Content-Encoding e, em seguida, abrir um InputStreamReader com o argumento correto. Uma verificação rápida da fonte não mostra nada que pareça fazer isso por você, o que parece muito ruim e sujeito a erros, então provavelmente esqueci alguma coisa.
cristão de

Respostas:

189

Resolveu meu próprio problema. Está linha:

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

precisa ser:

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

ou desde Java 7:

BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8));
Chris Kuehl
fonte
3
Tenho certeza de que a forma do construtor não gerará uma exceção na entrada inválida. Você precisa usar o com um CharsetDecoder decargumento. Este é o mesmo bug de design Java que os OutputStreamWriterconstrutores têm: apenas um dos quatro realmente condescende em dizer quando algo dá errado. Você também tem que usar o CharsetDecoder decargumento sofisticado aqui. A única coisa segura e sensata a fazer é considerar todos os outros construtores obsoletos, porque não se pode confiar neles.
tchrist
6
Desde Java 7, é possível escrever o conjunto de caracteres como uma constante, não como uma stringStandardCharsets.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) {

}

Experimente isto, .. :-)

Rohith
fonte
8
Em vez de file + = str, crie um StringBuilder e anexe a ele. O compilador pode ser capaz de otimizar o acréscimo de strings, mas provavelmente está criando muito lixo
volta de
2
Se você deseja converter um BufferedReader em uma string, use o Apache Commons, não reinvente a pápula: String myStr = org.apache.commons.io.IOUtils.toString (myBufferedReaderInstance);
Jaime Marín
8
UTF8 = "utf8", variável agradável;)
Nicofisi
7

Eu tive o mesmo problema toda vez que ele encontrava um caractere especial e o marcava como . para resolver isso, tentei usar a codificação: ISO-8859-1

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

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

}

Espero que isso possa ajudar quem vir este post.

joshua cleveland
fonte
1
Você poderia dizer quais são os caracteres não suportados em UTF-8?
USM