java - procesamiento - ¿Cómo convertir un Reader a InputStream y un Writer a OutputStream?
stream java examples (12)
¿Hay alguna manera fácil de evitar problemas de codificación de texto?
¿Estás tratando de escribir los contenidos de un Reader
en un OutputStream
? De ser así, le resultará más fácil OutputStream
el OutputStream
en un OutputStreamWriter
y escribir los caracteres del Reader
en el 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
Bueno, un Reader trata con los personajes 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.
En cuanto a cómo hacerlo, como se ha señalado, " los nombres obvios para estas clases son ReaderInputStream y WriterOutputStream " . Sorprendentemente, " estos no están incluidos en la biblioteca Java ", aunque las clases "opuestas", InputStreamReader y OutputStreamWriter son incluido.
Por lo tanto, mucha gente ha creado sus propias implementaciones, incluida 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 here ).
- Apache ReaderInputStream: enlace directo ReaderInputStream / código fuente
- Apache WriterOutputStream: enlace directo WriterOutputStream / código fuente
Como puede ver, la documentación de ambas clases establece que "todas las codificaciones de charset compatibles con JRE se manejan correctamente".
NB Un comentario sobre una de las otras respuestas aquí menciona issues.apache.org/bugzilla/show_bug.cgi?id=40455 . Pero eso afecta a la clase Apache Ant ReaderInputStream ( here ), no a la clase Apache Commons IO ReaderInputStream.
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 vaya a sortear todos los problemas de codificación de texto, que son una pesadilla.
Hay un RFE, pero está cerrado, no lo arreglará.
No puede evitar los 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 de código fuente.
Para leer una cadena en una secuencia usando solo lo que Java suministra.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));
Puedes usar Cactoos (no hay métodos estáticos, solo objetos):
Puedes convertir al revés también:
Realmente no puede evitar lidiar con los problemas de codificación de texto, pero existen soluciones existentes:
-
Reader
aInputStream
:ReaderInputStream
-
Writer
enOutputStream
:WriterOutputStream
Solo necesitas elegir la codificación que elijas.
Si comienzas con una cadena, también puedes hacer lo siguiente:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
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 solo paso utilizando org.apache.commons.io.IOUtils de Commons IO como lo siguiente:
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Por supuesto, todavía necesita pensar en la codificación de texto, pero al menos la conversión está sucediendo en un solo paso.
Una advertencia cuando se utiliza WriterOutputStream: no siempre maneja la escritura de datos binarios en un archivo correctamente / lo mismo que una secuencia de salida normal. Tuve un problema con esto que me llevó un tiempo rastrear.
Si puede, le recomendaría 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 confiable convertir texto en bytes que a la inversa, lo que probablemente sea el motivo por el cual WriterOutputStream no forma parte de la biblioteca estándar de Java.
Utilizar:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
De esta forma no se requiere una conversión inicial a String
y luego a byte[]
, que asigna mucha 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.