DataOutputStream#writeBytes(String)和BufferedWriter#write(String)有何区别?

6

我想为我的报告创建一个HTML文件。可以使用BufferedWriter#write(String)方法来创建报告中的内容。

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

或者通过使用 DataOutputStream#writeBytes(String) 方法

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

它们中的一个是否比另一个更好?为什么会这样?


考虑使用新的NIO.2文件API。 - Puce
@Puce 为什么要考虑这个? - user207421
1
@EJP 在Java SE 7中,java.io.File被认为是遗留API。http://docs.oracle.com/javase/tutorial/essential/io/legacy.html - Puce
3个回答

15

如果您要编写文本,则应使用Writer,它处理将Unicode字符(Java字符串的内部表示)转换为适当的字符编码,例如UTF-8。DataOutputStream.writeBytes仅输出字符串中每个char的低8位,并完全忽略高8位 - 这相当于对于ASCII字符(代码小于128(U+007F及以下))的UTF-8,但几乎肯定不适用于ASCII之外的任何内容。

您应该使用OutputStreamWriter而不是FileWriter,这样可以选择特定的编码(FileWriter始终使用平台的默认编码,因平台而异):

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

1
首先,在您的第二个示例中,DataOutputStream 没有任何有用的作用1。 实际上,如果您的字符串包含不适合 8 位的字符,则 writeBytes(String) 方法将破坏文本。 摆脱它。 数据流设计用于读取和写入细粒度二进制数据。 对于普通字节,请使用普通(或缓冲)输入或输出流。
其次,在这种特定的用例中,其中整个输出是单个写操作,BufferedWriter 也没有添加任何价值。
因此,在这种情况下,您应该进行比较:
    File f = new File("source.htm");
    Writer w = new FileWriter(f);
    w.write("Content");

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

依我看,第一版看起来更简单、更清晰。对于文本I/O,最好使用ReaderWriter堆栈...因为它们是为此而设计的。(它们可以干净、透明地处理编码和解码问题。)你可以在需要了解哪个更快(在你的系统上!)时对它们进行基准测试,但我怀疑它们之间没有太大的差异...而且第一版更快。1 - 我认为DataOutputStream在内部具有缓冲,但对于这种用例,缓冲并不会提高性能。


在进行多次(小)写操作而不是一次大写操作的情况下,使用BufferedWriter(或BufferedOutputStream)相比于未缓冲的写入器或流具有显着的性能优势。
另一个问题是你的代码两个版本都使用平台默认的字符编码来编码输出文件。更合适的做法可能是独立于默认值使用特定的编码,或将其作为配置或命令行参数。

1

输出流:

这个抽象类是所有表示字节输出流的类的超类。输出流接受输出字节并将它们发送到某个目标。

需要定义OutputStream子类的应用程序必须始终提供至少一种写入一个输出字节的方法。

例如:

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

BufferedWriter

Description:

将文本写入字符输出流,缓冲字符以提供单个字符、数组和字符串的高效写入。可以指定缓冲区大小,也可以接受默认大小。默认值对于大多数目的而言足够大。

提供了一个 newLine() 方法,它使用平台自己定义的行分隔符作为系统属性 line.separator。并非所有平台都使用换行符 ('\n') 终止行。因此,建议调用此方法来终止每个输出行,而不是直接写入换行符。

一般情况下,Writer 会立即将其输出发送到底层的字符或字节流中。除非需要及时输出,否则建议在任何可能成本很高的 Writer 的 write() 操作周围包装一个 BufferedWriter,例如 FileWritersOutputStreamWriters

Example:

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

1
直接引用JavaDocs而没有归属或进一步讨论并不构成答案... - Ian Roberts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接