Existe uma maneira fácil de evitar lidar com problemas de codificação de texto?
Existe uma maneira fácil de evitar lidar com problemas de codificação de texto?
Respostas:
Você realmente não pode evitar lidar com os problemas de codificação de texto, mas existem soluções no Apache Commons:
Reader
para InputStream
:ReaderInputStream
Writer
para OutputStream
:WriterOutputStream
Você só precisa escolher a codificação de sua escolha.
Se você está começando com uma String, também pode fazer o seguinte:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
ReaderInputStream
implementação exigiria menos memória - não deveria haver necessidade de armazenar todos os bytes em uma matriz de uma vez.
Bem, um Reader lida com caracteres e um InputStream lida com bytes. A codificação especifica como você deseja representar seus caracteres como bytes, portanto, você não pode realmente ignorar o problema. Quanto a evitar problemas, minha opinião é: escolha um conjunto de caracteres (por exemplo, "UTF-8") e continue com ele.
Em relação a como fazê-lo de fato, como foi apontado, " os nomes óbvios para essas classes são ReaderInputStream e WriterOutputStream . " Surpreendentemente, " eles não estão incluídos na biblioteca Java ", embora as classes 'opostas', InputStreamReader e OutputStreamWriter sejam incluído.
Portanto, muitas pessoas criaram suas próprias implementações, incluindo o 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 de conjunto de caracteres suportadas pelo JRE são tratadas corretamente".
NB Um comentário em uma das outras respostas aqui menciona esse bug . Mas isso afeta a classe Apache Ant ReaderInputStream ( aqui ), não a classe Apache Commons IO ReaderInputStream.
Observe também que, se você está começando com uma String, você pode pular a criação de um StringReader e criar um InputStream em uma etapa usando org.apache.commons.io.IOUtils do Commons IO assim:
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Claro que você ainda precisa pensar na codificação do texto, mas pelo menos a conversão está acontecendo em uma etapa.
new ByteArrayInputStream(report.toString().getBytes("utf-8"))
, o que envolve a alocação de duas cópias adicionais do relatório na memória. Se o relatório for grande, é ruim. Veja minha resposta.
Usar:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
Dessa forma, não é necessária uma conversão inicial para String
e depois para byte[]
, o que aloca muito mais memória heap, caso o relatório seja grande. Ele é convertido em bytes instantaneamente conforme o fluxo é lido, direto do StringBuffer.
Ele usa CharSequenceInputStream do projeto Apache Commons IO.
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.
Não tenho certeza se isso vai resolver todos os problemas de codificação de texto, que são um pesadelo.
Existe um RFE, mas está fechado, não corrige.
Você não pode evitar problemas de codificação de texto, mas o Apache commons-io tem
Observe que essas são as bibliotecas mencionadas na resposta de Peter de koders.com, apenas links para a biblioteca em vez do código-fonte.
Você está tentando escrever o conteúdo de um Reader
para um OutputStream
? Em caso afirmativo, você terá mais facilidade em agrupar o OutputStream
em um OutputStreamWriter
e escrever os char
de Reader
em em Writer
, em vez de tentar converter o leitor em 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
Um aviso ao usar WriterOutputStream - ele nem sempre lida com a gravação de dados binários em um arquivo corretamente / da mesma forma que um fluxo de saída regular. Eu tive um problema com isso que demorei um pouco para rastrear.
Se você puder, eu recomendo usar um fluxo de saída como sua base, e se você precisar escrever strings, use um wrapper OUtputStreamWriter ao redor do fluxo para fazer isso. É muito mais confiável converter texto em bytes do que o contrário, provavelmente porque WriterOutputStream não faz parte da biblioteca Java padrão
Você pode usar Cactoos (sem métodos estáticos, apenas objetos):
Você também pode converter o contrário:
Para ler uma string em um fluxo usando apenas o que o java fornece.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));