Java: diferencia entre PrintStream e PrintWriter

125

¿Cuál es la diferencia entre PrintStreamy PrintWriter? Tienen muchos métodos en común debido a que a menudo mezclo estas dos clases. Además, creo que podemos usarlos para exactamente las mismas cosas. Pero tiene que haber una diferencia, de lo contrario, habría habido solo una clase.

He buscado en los archivos, pero no pude encontrar esta pregunta.

Martijn Courteaux
fuente
1
+1 Buena pregunta, también mezclo estas dos clases, y el documento API tampoco ayuda mucho.
helpermethod
Otra diferencia es cómo funciona el lavado automático. Para un escritor, la presencia de un carácter \ n en la salida desencadena flush (). Pero en una secuencia de bytes (PrintStream) solo hay bytes. Autoflush funciona como se describe en Javadoc, basado en: "la propia noción de separador de línea de la plataforma en lugar del carácter de nueva línea".
minutos

Respuestas:

129

Esto puede sonar frívolo, pero se PrintStreamimprime en una OutputStream, y se PrintWriterimprime en una Writer. Ok, dudo que obtenga algún punto por decir lo obvio. Pero hay más.

Entonces, ¿cuál es la diferencia entre an OutputStreamy a Writer? Ambos son flujos, con la diferencia principal de que OutputStreames un flujo de bytes mientras que a Writeres un flujo de caracteres.

Si se OutputStreamtrata de bytes, ¿qué pasa PrintStream.print(String)? Convierte caracteres en bytes utilizando la codificación de plataforma predeterminada. El uso de la codificación predeterminada generalmente es algo malo, ya que puede generar errores al moverse de una plataforma a otra, especialmente si está generando el archivo en una plataforma y consumiéndolo en otra.

Con un Writer, normalmente especificas la codificación a usar, evitando las dependencias de la plataforma.

¿Por qué molestarse en tener un PrintStreamJDK, ya que la intención principal es escribir caracteres y no bytes? PrintStreames anterior a JDK 1.1 cuando se introdujeron secuencias de caracteres de Reader / Writer. Me imagino que Sun habría quedado en desuso PrintStreamsi solo fuera por el hecho de que es tan ampliamente utilizado. (¡Después de todo, no querrá que cada llamada System.outgenere una advertencia de API obsoleta! Además, cambiar el tipo de PrintStreama PrintWriterlas secuencias de salida estándar habría roto las aplicaciones existentes).

mdma
fuente
3
Esto es lo que yo también pensaba, pero no es cierto. Incluso PrintStream mantiene un escritor debajo del capó; si le pasa un OutputStream, lo envuelve.
Jon Skeet
3
@ Jon: internamente, hay un escritor, pero escribe en un OutputStream, por lo que el efecto neto es que un PrintStream escribe en un OutputStream - ocurre la conversión de bytes a bytes y utiliza la codificación de plataforma predeterminada. No existe tal requisito para la conversión de caracteres-> byte en un PrintWriter, puede quedarse con los caracteres hasta el final.
mdma
"El juego de caracteres predeterminado se determina durante el inicio de la máquina virtual y, por lo general, depende de la configuración regional y del juego de caracteres del sistema operativo subyacente", también Locale cambia el juego de caracteres predeterminado en algunas plataformas.
Pindatjuh
77
Desde Java 1.5, PrintStreamno se ha limitado al uso de la codificación predeterminada de la plataforma; Hay constructores que aceptan un nombre de juego de caracteres. Así, las distinciones entre PrintStreamy PrintWriterson que a PrintWriterno puede escribir bytes sin procesar y las dos clases envuelven diferentes tipos de destinos.
Ted Hopp
1
Podría valer la pena notar también una diferencia significativa en su comportamiento, mientras que efectivamente comparten PrintStreamlos print()métodos de una interfaz que son funciones de conveniencia que llaman write(), por lo que desencadenan el enjuague automático si está habilitado. PrintWriterpor otro lado, no se eliminará automáticamente después de una llamada a print(). He estado demostrando algunos Java para principiantes hoy y esto estaba atrapando a algunos estudiantes que no estaban familiarizados con la necesidad de descargar manualmente. De lo contrario, su respuesta es excelente.
Robadob
61

Con el PrintStreamestá atascado en la codificación predeterminada de la plataforma.

PrintStream stream = new PrintStream(output);

Sin PrintWriterembargo, con el puede pasar un OutputStreamWritercon una codificación específica.

PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8"));

La ventaja es, bueno, que puede controlar la codificación de caracteres, los caracteres deben escribirse de tal manera que finalmente no terminen como mojibake .

BalusC
fuente
12
Desde 1.4, hay un nuevo constructor para PrintStream que toma la codificaciónPrintStream(OutputStream out, boolean autoFlush, String encoding)
artbristol
19

Desde JDK 1.4 es posible especificar la codificación de caracteres para un PrintStream. Por lo tanto, las diferencias entre PrintStream e PrintWriter solo se refieren al comportamiento de enjuague automático y que un PrintStream no puede ajustar un escritor.

Renan Mozone
fuente
3

Los escritores como PrintWriter son para salida de texto, las secuencias son para salida binaria. Los escritores manejan las cosas del juego de caracteres para ti. Las transmisiones no lo hacen porque se supone que no desea ese tipo de conversión, lo que estropearía sus datos binarios y utilizaría un escritor si lo hiciera.

sblundy
fuente
1
Excepto PrintStream, porque esa toma una codificación para que pueda manejar un poco más que un OutputStream estándar.
Simon Groenewolt
Suena extraño que System.out, cuyo único objetivo es imprimir cadenas, sea en realidad un PrintStream.
minutos
"Los escritores manejan las cosas del juego de caracteres por usted", solo los escritores que se ocupan de convertir caracteres en bytes. No todos los escritores lo hacen.
Aivar
2

Puede escribir bytes sin formato en una secuencia y no en un escritor. Los PrintStream listas javadoc las otras diferencias (que es más importante, ser capaz de establecer una codificación en una corriente para que pueda interpretar los bytes sin diría yo).

Simon Groenewolt
fuente
Con PrintStream también se puede especificar la codificación
Aivar
1

del núcleo de Java por Horstmann

Los veteranos de Java podrían preguntarse qué pasó con la clase PrintStream y System.out. En Java 1.0, la clase PrintStream simplemente truncó todos los caracteres Unicode a caracteres ASCII al soltar el byte superior. (En ese momento, Unicode todavía era una codificación de 16 bits). Claramente, ese no era un enfoque limpio o portátil, y se solucionó con la introducción de lectores y escritores en Java 1.1. Por compatibilidad con el código existente, System.in, System.out y System.err siguen siendo flujos de entrada / salida, no lectores y escritores. Pero ahora la clase PrintStream convierte internamente los caracteres Unicode a la codificación de host predeterminada de la misma manera que lo hace PrintWriter. Los objetos de tipo PrintStream actúan exactamente como los escritores de impresión cuando usas los métodos print e println,

nichijou
fuente
-3

Printwriter es una mejora del flujo de impresión.

IE printstream para un propósito específico.

Spoo
fuente