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");

其中一个比另一个更好吗?为什么会这样?

4

3 回答 3

15

如果您正在写出文本,那么您应该使用 a Writer,它处理从 unicode 字符(Java 的字符串的内部表示)到适当的字符编码(例如 UTF-8)的转换。 DataOutputStream.writeBytes简单地输出字符串中每个的低八位char并完全忽略高八位 - 这相当于 UTF-8 用于编码低于 128(U+007F 及以下)的 ASCII 字符,但几乎可以肯定任何事情都是错误的超越 ASCII。

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

File f = new File("source.htm");
BufferedWriter bw = new BufferedWriter(
  new OutputStreamWriter(new FileOutputStream(f), "UTF-8"));
bw.write("Content");
于 2013-12-03T13:08:50.427 回答
1

首先,您的第二个示例中的1DataOutputStream没有用处。实际上,如果您的字符串包含不适合 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());

在我看来,第一个版本看起来更简单、更干净。最好将ReaderWriter堆栈用于文本 I/O ......因为这就是它们的设计目的。(他们干净透明地处理编码和解码问题。)

如果您真的需要知道哪个更快(在您的系统上!),您可以对它们进行基准测试,但我怀疑没有太大区别......而且第一个版本更快。

1 - 我认为 DataOutputStream 在幕后有缓冲,但对于这个用例,缓冲无助于提高性能。


在执行多个(小)写入而不是大写入的用例中,使用 a BufferedWriter(或 a BufferedOutputStream)而不是无缓冲的写入器或流具有显着的性能优势。


另一点是您的代码的两个版本都使用平台的默认字符编码来编码输出文件。使用独立于默认编码的特定编码可能更合适,或者将其作为配置或命令行参数。

于 2013-12-03T13:17:44.010 回答
1

输出流:

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

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

例如:

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

缓冲写入器

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

提供了一种newLine()方法,该方法使用系统属性 line.separator 定义的平台自己的行分隔符概念。并非所有平台都使用换行符 ('\n') 来终止行。因此,调用此方法来终止每个输出行优于直接写入换行符。

通常,Writer 将其输出立即发送到底层字符或字节流。除非需要快速输出,否则建议将 a 包裹BufferedWriter在任何操作可能成本高昂的 Writer 周围write(),例如FileWritersOutputStreamWriters

例如:

 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
于 2013-12-03T13:21:41.427 回答