PrintWriter 是否缓冲?

Is PrintWriter buffered?

我知道写格式化数据用PrintWriter很好,我也知道用BufferedWriter提高IO性能

但我试过这样的方法,

PrintWriter pw = new PrintWriter(System.out);
pw.println("Statement 1");
pw.println("Statement 2");
//pw.flush();

我观察到当 flush 方法被注释时没有输出,但是当我取消注释时,我得到了想要的输出。

这只有在 PrintWriter 被缓冲时才有可能。如果是这样,那么使用 BufferedWriter 包装 PrintWriter 然后写入它有什么意义?

虽然 javadoc 没有在任何地方提到 PrintWriter 是缓冲的,但看起来是这样。

来自 Java 8 PrintWriter 的来源

/**
 * Creates a new PrintWriter from an existing OutputStream.  This
 * convenience constructor creates the necessary intermediate
 * OutputStreamWriter, which will convert characters into bytes using the
 * default character encoding.
 *
 * @param  out        An output stream
 * @param  autoFlush  A boolean; if true, the <tt>println</tt>,
 *                    <tt>printf</tt>, or <tt>format</tt> methods will
 *                    flush the output buffer
 *
 * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
 */
public PrintWriter(OutputStream out, boolean autoFlush) {
    this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);

您可以看到 PrintWriter 使用 BufferedWriter 并且它有一个选项 autoFlush 只有在缓冲时才有意义。

PrintWriter 已缓冲。不同之处在于 PrintWriter 提供了方便的方法来编写对象的格式化字符串表示形式,如 println()printf()。它还具有自动刷新功能(显然它具有缓冲区)。

两个类都有效。如果您启用 PrintWriter 的自动刷新,那么它可能不会如此(因为每次您调用 println() 之类的东西时它都会刷新)。另一个区别是 PrintWriter 并不是真的让你直接写字节。

我检查了从 1.6.0_45 开始的 JDK 个版本,它们都有 this 个构造函数存在:

/**
 * Creates a new PrintWriter from an existing OutputStream.  This
 * convenience constructor creates the necessary intermediate
 * OutputStreamWriter, which will convert characters into bytes using the
 * default character encoding.
 *
 * @param  out        An output stream
 * @param  autoFlush  A boolean; if true, the <tt>println</tt>,
 *                    <tt>printf</tt>, or <tt>format</tt> methods will
 *                    flush the output buffer
 *
 * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
 */
public PrintWriter(OutputStream out, boolean autoFlush) {
this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);

因此 PrintWritter 使用缓冲输出。如果您想使用您指出的代码,您可以创建 PrintWriter 并将 autoflush 设置为 true,这将确保使用一个println, printf or format 方法中的一个会刷新流。因此,在给定的上下文中,您的代码将如下所示:

PrintWriter pw = new PrintWriter(System.out, true);
pw.println("Statement 1");
pw.println("Statement 2");

我认为由于 PrintWriter 也可以一次读取字符串,所以它会使用缓冲区。