2008-09-15 11 views

Respuesta

34

Realmente no se puede evitar tratar con los problemas de codificación de texto, pero hay soluciones existentes:

Sólo necesita elegir la codificación que elijas.

+6

FYI: el código ReaderInputStream tiene un error en la forma en que lee los bytes (no funcionará para todas las codificaciones). Prueba: http://illegalargumentexception.blogspot.com/2009/05/java-rough-guide-to-character-encoding.html#javaencoding_stringclass Hay un error abierto: https://issues.apache.org/bugzilla/show_bug .cgi? id = 40455 – McDowell

+0

También el código es copyright :( – Armand

+1

Puede encontrar las clases en la biblioteca commons-io de Apache: http://commons.apache.org/proper/commons-io/ –

5

Los nombres obvios para estas clases son ReaderInputStream y WriterOutputStream. Lamentablemente, estos no están incluidos en la biblioteca de Java. Sin embargo, google es tu amigo.

No estoy seguro de que va a solucionar todos los problemas de codificación de texto, que son una pesadilla.

There is an RFE, pero está cerrado, no se solucionará.

+1

https://bugs.openjdk.java.net/browse/JDK-4103785 contiene comentarios "tenemos una API pública para el juego de caracteres de codificación ... ninguna razón de peso para agregar estos clases "- entonces, ¿cómo se hace esto en Java 7, sin bibliotecas adicionales, doce años en el futuro? –

4

¿Está tratando de escribir el contenido de un Reader en un OutputStream? Si es así, tendrá un tiempo más fácil envolver el OutputStream en un OutputStreamWriter y escribe los char s de la Reader a la Writer, en lugar de tratar de convertir al lector a 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 
16

nota también de que, si estás empezando con una cadena, puede omitir la creación de un StringReader y crear un InputStream en un solo paso utilizando org.apache.commons.io.IOUtils de Commons IO así:

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

por supuesto que aún necesita pensar en la codificación de texto, pero en lea st la conversión está sucediendo en un solo paso.

+2

Este método básicamente hace 'nuevo ByteArrayInputStream (report.toString(). GetBytes ("utf-8")) ', que implica la asignación de dos copias adicionales del informe en la memoria. Si el informe es grande, es incorrecto. Consulte mi respuesta. – Oliv

87

Si usted está comenzando con una cadena que también puede hacer lo siguiente:

new ByteArrayInputStream(inputString.getBytes("UTF-8")) 
+2

Esto resuelve una problema con la cadena, pero no con la original – sbeliakov

+6

La buena implementación de 'ReaderInputStream' requeriría menos memoria, no debería haber necesidad de almacenar todos los bytes en una matriz a la vez. –

+3

Me gusta esta solución porque funciona cuando se necesita unidad código de prueba que acepta entrada en (por ejemplo) entrada estándar. –

5

No se puede evitar problemas de codificación de texto, pero tiene Apache commons-io

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 de código fuente.

35

Bueno, un lector se ocupa de los caracteres y un InputStream se ocupa de los bytes. La codificación especifica cómo deseas representar a tus personajes como bytes, por lo que no puedes 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.

con respecto a cómo lo hacen realmente, como se ha señalado, "los nombres obvios para estas clases son ReaderInputStream y WriterOutputStream." Sorprendentemente, "éstos no están incluidos en la biblioteca de Java" aunque las clases 'opuestas', InputStreamReader y OutputStreamWriterson incluidas.

Por lo tanto, mucha gente ha creado sus propias implementaciones, incluyendo ApacheCommons IO. Según los problemas de licencia, es probable que pueda incluir la biblioteca commons-io en su proyecto, o incluso copiar una parte del código fuente (que se puede descargar here).

Como se puede ver, la documentación de ambas clases afirma que "todas las codificaciones de juegos de caracteres soportados por el JRE se manejan correctamente" .

N.B. Un comentario sobre una de las otras respuestas aquí menciona this bug. Pero eso afecta al Apache Ant clase ReaderInputStream (here), no Apache Commons IO clase ReaderInputStream.

1

Una advertencia cuando se utiliza WriterOutputStream - no siempre maneja la escritura de datos binarios a un archivo correctamente/lo mismo que una secuencia de salida normal. Tuve un problema con esto que me llevó un tiempo rastrear.

Si puede, recomiendo usar una secuencia de salida como su base, y si necesita escribir cadenas, use un contenedor OUtputStreamWriter alrededor de la secuencia para hacerlo. Es mucho más fiable para convertir texto en bytes que el revés, que es probable por la WriterOutputStream no es una parte de la biblioteca estándar de Java

7

Uso:

new CharSequenceInputStream(html, StandardCharsets.UTF_8); 

De esta manera no requiere un adelantado conversión a String y luego a byte[], que asigna mucho más memoria de montón, en caso de que el informe sea grande. Se convierte en bytes sobre la marcha a medida que se lee la secuencia, directamente desde StringBuffer.

Utiliza CharSequenceInputStream del proyecto Apache Commons IO.

-1

Para leer una cadena en una secuencia con solo lo que Java suministra.

InputStream s = new BufferedInputStream(new ReaderInputStream(new StringReader("a string"))); 
+5

ReaderInputStream se encuentra en Apache Commons IO. –

Cuestiones relacionadas