it-swarm-pt.tech

Como converter um Reader para InputStream e um Writer para OutputStream?

Existe uma maneira fácil de evitar lidar com problemas de codificação de texto?

85
Andrei Savu

Você não pode realmente evitar lidar com os problemas de codificação de texto, mas existem soluções existentes:

Você só precisa escolher a codificação de sua escolha.

42
Peter

Se você está começando com uma String, você também pode fazer o seguinte:

new ByteArrayInputStream(inputString.getBytes("UTF-8"))
93
Ritesh Tendulkar

Bem, um leitor lida com caracteres e um tráfego de InputStream com bytes. A codificação especifica como você deseja representar seus caracteres como bytes, então você não pode realmente ignorar o problema. Quanto a evitar problemas, minha opinião é: escolha um charset (por exemplo, "UTF-8") e fique com ele.

Em relação a como realmente fazer isso, como foi apontado, " os nomes óbvios para essas classes são ReaderInputStream e WriterOutputStream . "Surpreendentemente," estes não estão incluídos na biblioteca Java "mesmo que as classes 'opostas', InputStreamReader e OutputStreamWriter sejam incluídas.

Então, muitas pessoas criaram suas próprias implementações, incluindo Apache Commons IO . Dependendo dos problemas de licenciamento, você provavelmente poderá incluir a biblioteca commons-io em seu projeto, ou até mesmo copiar uma parte do código-fonte (que pode ser baixado aqui ).

Como você pode ver, a documentação de ambas as classes afirma que "todas as codificações charset suportadas pelo JRE são tratadas corretamente".

N.B. Um comentário sobre uma das outras respostas aqui menciona este bug . Mas isso afeta o Apache Ant classe ReaderInputStream ( aqui ), não o Apache Classe IO do tipo ReaderInputStream.

39
Peter Ford

Observe também que, se você está começando com um String, você pode pular a criação de um StringReader e criar um InputStream em uma única etapa usando org.Apache.commons.io.IOUtils de Commons IO da seguinte forma:

InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");

É claro que você ainda precisa pensar sobre a codificação do texto, mas pelo menos a conversão está acontecendo em uma única etapa.

19
Phil Harvey

Usar:

new CharSequenceInputStream(html, StandardCharsets.UTF_8);

Dessa forma, não é necessária uma conversão inicial para String e, em seguida, para byte[], que aloca muito mais memória heap, caso o relatório seja grande. Converte para bytes em tempo real como o fluxo é lido, diretamente do StringBuffer.

Ele usa CharSequenceInputStream do projeto Apache Commons IO.

8
Oliv
7
Bozho

Você não pode evitar problemas de codificação de texto, mas Apache commons-io tem

Observe que essas são as bibliotecas mencionadas na resposta de Peter do koders.com, apenas links para a biblioteca em vez do código-fonte.

5
dfrankow

Os nomes óbvios para essas classes são ReaderInputStream e WriterOutputStream. Infelizmente, eles não estão incluídos na biblioteca Java. No entanto, o google é seu amigo.

Eu não tenho certeza de que isso vai contornar todos os problemas de codificação de texto, que são um pesadelo.

Existe um RFE, mas está fechado, não irá corrigir.

5
Tom Hawtin - tackline

Você está tentando gravar o conteúdo de um Reader para um OutputStream? Em caso afirmativo, você terá um tempo mais fácil envolvendo o OutputStream em um OutputStreamWriter e escreva o chars do Reader para o Writer, em vez de tentar converter o leitor para um InputStream:

final Writer writer = new BufferedWriter(new OutputStreamWriter( urlConnection.getOutputStream(), "UTF-8" ) );
int charsRead;
char[] cbuf = new char[1024];
while ((charsRead = data.read(cbuf)) != -1) {
    writer.write(cbuf, 0, charsRead);
}
writer.flush();
// don't forget to close the writer in a finally {} block
4
Sam Barnum

Você pode usar Cactoos (sem métodos estáticos, apenas objetos):

Você pode converter o contrário também:

1
yegor256

Um aviso ao usar o WriterOutputStream - ele nem sempre manipula a gravação de dados binários em um arquivo corretamente/o mesmo que um fluxo de saída regular. Eu tive um problema com isso que me levou algum tempo para rastrear.

Se puder, recomendo usar um fluxo de saída como base e, se precisar gravar strings, use um wrapper OUtputStreamWriter ao redor do fluxo para fazê-lo. É muito mais confiável converter texto em bytes do que o inverso, o que provavelmente explica porque o WriterOutputStream não faz parte da biblioteca padrão Java

1
romeara