【问题标题】:DataOutputStream#writeBytes(String) vs BufferedWriter#write(String)DataOutputStream#writeBytes(String) 与 BufferedWriter#write(String)
【发布时间】:2013-12-03 13:03:47
【问题描述】:

我想为我的报告创建一个 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");

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

【问题讨论】:

标签: java string java-io bufferedwriter dataoutputstream


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    首先,第二个示例中的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());
    

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

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

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


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


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

    【讨论】:

      【解决方案3】:

      输出流:

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

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

      例如:

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

      BufferedWriter

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

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

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

      例如:

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

      【讨论】:

      • 来自 JavaDocs 的直接引用,没有署名或进一步讨论不构成答案......
      猜你喜欢
      • 1970-01-01
      • 2018-08-09
      • 2016-07-10
      • 2010-09-24
      • 2010-10-12
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多