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

时间:2013-12-03 13:03:48

标签: java string java-io bufferedwriter dataoutputstream

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

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

3 个答案:

答案 0 :(得分:15)

如果您正在写出文本,那么您应该使用Writer来处理从unicode字符(Java的字符串内部表示)到适当的字符编码(如UTF-8)的转换。 DataOutputStream.writeBytes只输出字符串中每个char的低位8位,并完全忽略高位8位 - 这相当于代码低于128的ASCII字符的UTF-8(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");

答案 1 :(得分: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());

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

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

1 - 我认为DataOutputStream具有缓冲功能,但对于此用例,缓冲无助于提升性能。


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


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

答案 2 :(得分:1)

<强>的OutputStream:

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

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

例如:

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

<强> 的BufferedWriter

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

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

通常,Writer会立即将其输出发送到基础字符或字节流。除非需要提示输出,否则建议在BufferedWriter操作可能代价高昂的任何Writer周围包裹write(),例如FileWritersOutputStreamWriters

例如:

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