DataOutputStream#writeBytes(String) vs BufferedWriter#write(String)

Me gustaría crear un archivo HTML para mi informe. El contenido del informe se puede crear utilizando BufferedWriter#write(String)

File f = new File("source.htm");
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
bw.write("Content");

o usando DataOutputStream#writeBytes(String)

File f = new File("source.htm");
DataOutputStream dosReport = new DataOutputStream(new FileOutputStream(f)); 
dosReport.wrtiteBytes("Content");

¿Es uno de ellos mejor que el otro? ¿Por que es esto entonces?

preguntado el 03 de diciembre de 13 a las 13:12

posible duplicado de Writer o OutputStream? -

Considere utilizar la nueva API de archivos NIO.2. -

@Puce ¿Considéralo por qué? -

@EJP java.io.File se considera una API heredada en Java SE 7. docs.oracle.com/javase/tutorial/essential/io/legacy.html -

3 Respuestas

Si está escribiendo texto, debe usar un Writer, que maneja la conversión de caracteres Unicode (la representación interna de cadenas de Java) en una codificación de caracteres adecuada, como UTF-8. DataOutputStream.writeBytes simplemente genera los ocho bits de orden inferior de cada char en la cadena e ignora por completo los ocho bits de orden superior; esto es equivalente a UTF-8 para caracteres ASCII con códigos por debajo de 128 (U+007F y por debajo), pero es casi seguro que es incorrecto para cualquier cosa más allá de ASCII.

En lugar de un FileWriter, debe usar un OutputStreamWriter para poder seleccionar una codificación específica (FileWriter siempre usa la codificación predeterminada de la plataforma, que varía de una plataforma a otra):

File f = new File("source.htm");
BufferedWriter bw = new BufferedWriter(
  new OutputStreamWriter(new FileOutputStream(f), "UTF-8"));
bw.write("Content");

Respondido el 03 de diciembre de 13 a las 13:12

En primer lugar, la DataOutputStream en su segundo ejemplo no tiene ningún propósito útil1. De hecho, si sus cadenas contienen caracteres que no caben en 8 bits, el writeBytes(String) método va a destrozar el texto. Desaste de eso. Los flujos de datos están diseñados para leer y escribir datos binarios detallados. Para bytes simples, use un flujo de entrada o salida simple (o almacenado en búfer).

Secondly, in this specific use-case where you writing the entire output is a single write operation, the BufferedWriter doesn't add any value either.

Así que en este caso. deberías estar comparando:

    File f = new File("source.htm");
    Writer w = new FileWriter(f);
    w.write("Content");

frente a

    File f = new File("source.htm");
    OutputStream os = new FileOutputStream(f); 
    os.write("Content".getBytes());

En mi opinión, la primera versión parece más simple y limpia. Y lo mejor es usar el Reader y Writer pilas para E/S de texto... porque para eso fueron diseñadas. (Se encargan de los problemas de codificación y decodificación, de forma limpia y transparente).

Podría compararlos si realmente necesita saber cuál es más rápido (¡en su sistema!) pero sospecho que no hay mucha diferencia... y que la primera versión es más rápida.

1: creo que DataOutputStream tiene almacenamiento en búfer oculto, pero para este caso de uso, el almacenamiento en búfer no ayuda al rendimiento.


En los casos de uso en los que realiza varias escrituras (pequeñas) en lugar de una grande, existe una ventaja de rendimiento significativa al usar un BufferedWriter (O un BufferedOutputStream) en lugar de un escritor o flujo sin búfer.


El otro punto es que ambas versiones de su código utilizan la codificación de caracteres predeterminada de la plataforma para codificar el archivo de salida. Puede ser más apropiado usar una codificación específica independientemente de la predeterminada, o convertirla en un parámetro de línea de comando o de configuración.

Respondido el 04 de diciembre de 13 a las 04:12

Flujo de salida:

Esta clase abstracta es la superclase de todas las clases que representan un flujo de salida de bytes. Un flujo de salida acepta bytes de salida y los envía a algún sumidero.

Aplicaciones que necesitan definir una subclase de OutputStream siempre debe proporcionar al menos un método que escriba un byte de salida.

Por ejemplo:

OutputStream os = new FileOutputStream("test.txt");

Escritor en búfer

Escribe texto en un flujo de salida de caracteres, almacenando en búfer los caracteres para permitir la escritura eficiente de caracteres individuales, matrices y cadenas. Se puede especificar el tamaño del búfer o se puede aceptar el tamaño predeterminado. El valor predeterminado es lo suficientemente grande para la mayoría de los propósitos.

A newLine() se proporciona el método, que utiliza la propia noción de separador de línea de la plataforma tal como se define en la propiedad del sistema line.separator. No todas las plataformas usan el carácter de nueva línea ('\n') para terminar las líneas. Por lo tanto, se prefiere llamar a este método para terminar cada línea de salida a escribir un carácter de nueva línea directamente.

En general, un escritor envía su salida inmediatamente al carácter subyacente o al flujo de bytes. A menos que se requiera una salida rápida, es recomendable envolver un BufferedWriter alrededor de cualquier escritor cuyo write() las operaciones pueden ser costosas, como FileWriters y OutputStreamWriters.

Por ejemplo:

 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));

Respondido el 30 de diciembre de 16 a las 22:12

Una cita directa de JavaDocs sin atribución o discusión adicional no constituye una respuesta... - Ian Roberts

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.