本文介绍了PrintWriter vs PrintStream vs OutputStreamWriter timecosts的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如你所知,我们在java中有几个用于将数据写入流的工具。

在这个示例代码中,我通过运行时对它们进行了比较。

有人可以解释一下吗?谢谢。

以下是代码:

As you know we have several tools in java for writing data into streams.
In this sample code I have compared them by runtime.
Can somebody explain it exactly? Thanks.
Here is the code:

import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;

public class IOtests
{

public static void main(String[] args) throws Exception
{
    char[] chars = new char[100];
    byte[] bytes = new byte[100];
    for (int i = 0; i < 100; i++)
    {
        chars[i] = (char) i;
        bytes[i] = (byte) i;
    }
    OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(
            "output.txt"));
    long a = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
        for (char j : chars)
            out.write(j);
    System.out.println("OutputStreamWriter writing characters: "
            + (System.currentTimeMillis() - a));
    out = new OutputStreamWriter(new FileOutputStream("output.txt"));
    a = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
        for (byte j : bytes)
            out.write(j);
    System.out.println("OutputStreamWriter writing bytes: "
            + (System.currentTimeMillis() - a));
    PrintStream out1 = new PrintStream("output.txt");
    a = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
        for (char j : chars)
            out1.write(j);
    System.out.println("PrintStream writing characters: "
            + (System.currentTimeMillis() - a));
    out1 = new PrintStream("output.txt");
    a = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
        for (byte j : bytes)
            out1.write(j);
    System.out.println("PrintStream writing bytes: "
            + (System.currentTimeMillis() - a));
    PrintWriter out2 = new PrintWriter("output.txt");
    a = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
        for (char j : chars)
            out2.write(j);
    System.out.println("PrintWriter writing characters: "
            + (System.currentTimeMillis() - a));
    out1 = new PrintStream("output.txt");
    a = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
        for (byte j : bytes)
            out2.write(j);
    System.out.println("PrintWriter writing bytes: "
            + (System.currentTimeMillis() - a));
}

}

结果:

请注意,所有时间都以毫秒为单位。

Note that all times are in milliseconds.

推荐答案

我已将问题简化为其本质:

I've reduced your question to its essence:

public class Test {
  static byte[] bytes = new byte[10_000_000];
  static {
    for (int i = 0; i < bytes.length; i++) bytes[i] = (byte) (i%100+32);
  }
  public static void main(String[] args) throws Exception {
    writer(true);
    writer(false);
    stream(true);
    stream(false);
  }

  static void writer(boolean flush) throws IOException {
    Writer out = new FileWriter("output.txt");
    long a = System.currentTimeMillis();
    for (byte j : bytes) {
      out.write(j);
      if (flush) out.flush();
    }
    out.close();
    System.out.println("FileWriter with" + (flush? "":"out") + " flushing: " +
        (System.currentTimeMillis() - a));
  }
  static void stream(boolean flush) throws IOException {
    OutputStream out = new FileOutputStream("output.txt");
    long a = System.currentTimeMillis();
    for (byte j : bytes) {
      out.write(j);
      if (flush) out.flush();
    }
    out.close();
    System.out.println("FileOutputStream with" + (flush? "":"out") + " flushing: " +
        (System.currentTimeMillis() - a));
  }
}

注意:


  • 完成后正确关闭资源;

  • 双循环替换为单循环,但更大的数组;

  • 避免编写控制字符以逃避autoflush行为;

  • 仅使用字节数组,因为在所有情况下只测试一种方法: write(int)。因此,无论您使用字节还是字符都没有区别;

  • 除了 FileWriter 之外的所有内容FileOutputStream 因为所有其他情况归结为这两个;

  • 以两种模式测试编写器和输出流:每次写入后刷新,不要刷新所有直到关闭。

  • properly closing the resources when done;
  • double loop replaced by single loop, but a larger array;
  • avoid writing control characters to evade autoflush behavior;
  • only using byte array since you are testing only one method in all cases: write(int). Therefore it makes no difference whether you are using bytes or chars;
  • removed everything except a FileWriter and a FileOutputStream because all other cases boil down to these two;
  • testing both writer and output stream in two modes: flush after each write, and don't flush at all until close.

现在,当你运行它时,你会得到如下输出:

Now, when you run this, you'll get output like the following:

FileWriter with flushing: 28235
FileWriter without flushing: 828
FileOutputStream with flushing: 23984
FileOutputStream without flushing: 23641

那么,教训是什么?


  • 所有编写器都是缓冲的,因为它们内部委托给 StreamEncoder ,它本身是缓冲的;

  • FileOutputStream 未缓冲;

  • 非缓冲的逐字节写入非常慢。

  • all writers are buffered because internally they delegate to StreamEncoder which is itself buffered;
  • FileOutputStream is not buffered;
  • non-buffered writing byte-by-byte is very slow.

良好实践要求您始终执行缓冲写入:使用缓冲接收器或维护显式缓冲区在你身边。

Good practices demand that you always do buffered writing: either using buffered sinks, or maintaining an explicit buffer on your side.

这篇关于PrintWriter vs PrintStream vs OutputStreamWriter timecosts的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 15:37