¿Existe una forma sencilla de evitar los problemas de codificación de texto?
¿Existe una forma sencilla de evitar los problemas de codificación de texto?
Respuestas:
Realmente no puede evitar lidiar con los problemas de codificación de texto, pero existen soluciones en Apache Commons:
Reader
para InputStream
:ReaderInputStream
Writer
para OutputStream
:WriterOutputStream
Solo necesita elegir la codificación de su elección.
Si está comenzando con una cadena, también puede hacer lo siguiente:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
ReaderInputStream
implementación requeriría menos memoria; no debería ser necesario almacenar todos los bytes en una matriz a la vez.
Bueno, un Reader se ocupa de los caracteres y un InputStream se ocupa de los bytes. La codificación especifica cómo desea representar sus caracteres como bytes, por lo que realmente no puede ignorar el problema. En cuanto a evitar problemas, mi opinión es: elija un juego de caracteres (por ejemplo, "UTF-8") y quédese con él.
En cuanto a cómo hacerlo realmente, como se ha señalado, " los nombres obvios para estas clases son ReaderInputStream y WriterOutputStream " . Sorprendentemente, " estos no están incluidos en la biblioteca de Java " aunque las clases 'opuestas', InputStreamReader y OutputStreamWriter son incluido.
Por lo tanto, muchas personas han creado sus propias implementaciones, incluido Apache Commons IO . Dependiendo de los problemas de licencia, probablemente podrá incluir la biblioteca commons-io en su proyecto, o incluso copiar una parte del código fuente (que se puede descargar aquí ).
Como puede ver, la documentación de ambas clases establece que "todas las codificaciones de conjuntos de caracteres admitidas por JRE se manejan correctamente".
NB Un comentario sobre una de las otras respuestas aquí menciona este error . Pero eso afecta a la clase Apache Ant ReaderInputStream ( aquí ), no a la clase Apache Commons IO ReaderInputStream.
También tenga en cuenta que, si está comenzando con un String, puede omitir la creación de un StringReader y crear un InputStream en un paso usando org.apache.commons.io.IOUtils de Commons IO así:
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Por supuesto, aún debe pensar en la codificación del texto, pero al menos la conversión se realiza en un solo paso.
new ByteArrayInputStream(report.toString().getBytes("utf-8"))
, lo que implica la asignación de dos copias adicionales del informe en la memoria. Si el informe es grande, es malo. Mira mi respuesta.
Utilizar:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
De esta forma no se requiere una conversión inicial a String
y luego abyte[]
, lo que asigna mucha más memoria de pila, en caso de que el informe sea grande. Se convierte a bytes sobre la marcha a medida que se lee la secuencia, directamente desde StringBuffer.
Utiliza CharSequenceInputStream del proyecto Apache Commons IO.
Los nombres obvios para estas clases son ReaderInputStream y WriterOutputStream. Desafortunadamente, estos no están incluidos en la biblioteca de Java. Sin embargo, Google es tu amigo.
No estoy seguro de que vaya a solucionar todos los problemas de codificación de texto, que son una pesadilla.
Hay un RFE, pero está cerrado, no se solucionará.
No puede evitar problemas de codificación de texto, pero Apache commons-io tiene
Tenga en cuenta que estas son las bibliotecas a las que se hace referencia en la respuesta de Peter de koders.com, solo enlaces a la biblioteca en lugar del código fuente.
¿Estás intentando escribir el contenido de un Reader
a un OutputStream
? Si es así, le resultará más fácil ajustar el OutputStream
en an OutputStreamWriter
y escribir la char
s de la Reader
a la Writer
, en lugar de intentar convertir el lector en un 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
Una advertencia al usar WriterOutputStream: no siempre maneja la escritura de datos binarios en un archivo correctamente / igual que un flujo de salida normal. Tuve un problema con esto que me tomó un tiempo localizarlo.
Si puede, le recomiendo usar un flujo de salida como base, y si necesita escribir cadenas, use un contenedor OUtputStreamWriter alrededor del flujo para hacerlo. Es mucho más confiable convertir texto a bytes que al revés, razón por la cual WriterOutputStream no es parte de la biblioteca estándar de Java.
Puedes usar Cactoos (sin métodos estáticos, solo objetos):
También puede convertir al revés:
Para leer una cadena en una secuencia usando solo lo que proporciona Java.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));