首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >立即看到System.out.print输出到控制台。所以PrintStream在每次打印后都会刷新,而不仅仅是println?

立即看到System.out.print输出到控制台。所以PrintStream在每次打印后都会刷新,而不仅仅是println?
EN

Stack Overflow用户
提问于 2017-06-07 09:03:18
回答 2查看 930关注 0票数 2

来自PrintStream 文档

可以选择地创建PrintStream,以便自动刷新;这意味着在写入字节数组()、调用println方法之一()或写入换行符或字节('\n')之后,会自动调用方法。

然后给出代码

代码语言:javascript
复制
System.out.print("hi");   // gives console output: hi
System.out.print(7);      // gives console output: 7

// prevents flushing when stream wiil be closed at app shutdown
for (;;) {
}

,为什么我看到输出到我的控制台?不应该写任何东西来安慰(来自System.out的PrintStream实例),,因为到目前为止什么都不会被刷新!

没有回答这个问题。

我想答案是在源代码中(私有实用程序方法BufferedWriter.flushBuffer()),但我不理解对代码的注释:“将输出缓冲区刷新到底层字符流,而不刷新流本身”:如果PrintStream (与控制台输出绑定),即“流本身”未刷新,则不应刷新到控制台的输出!

PrintStream.print源(String):

代码语言:javascript
复制
private void write(String s) {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.write(s);
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush && (s.indexOf('\n') >= 0))
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }

BufferedWriter.flushBuffer()的来源:

代码语言:javascript
复制
/**
     * Flushes the output buffer to the underlying character stream, without
     * flushing the stream itself.  This method is non-private only so that it
     * may be invoked by PrintStream.
     */
    void flushBuffer() throws IOException {
        synchronized (lock) {
            ensureOpen();
            if (nextChar == 0)
                return;
            out.write(cb, 0, nextChar);
            nextChar = 0;
        }
    }

更多细节也给出了这里。这是非常复杂的,但似乎在某个阶段,BufferedWriter被赋予了PrintStream构造函数。

EN

回答 2

Stack Overflow用户

发布于 2017-06-07 09:06:41

我一步一步地使用调试器,这就是我发现的:

String s在527行后显示在控制台中,因此它在第528行之前,在第528行中完成了\n的检查。

charOut.flushBuffer()内部深处,有以下方法称为:

其中,关于\n的检查丢失了。

流动情况如下:

  1. System.out#print(String s)打电话给PrintStream#print(String s)
  2. PrintStream#print(String s)打电话给PrintStream#write(String s)
  3. PrintStream#write(String s)打电话给OutputSteamWriter#flushBuffer()
  4. OutputStreamWriter#flushBuffer()打电话给StreamEncoder#flushBuffer()
  5. StreamEncoder#flushBuffer()打电话给StreamEncoder#implFlushBuffer()
  6. StreamEncoder#implFlushBuffer()打电话给StreamEncoder#writeBytes()
  7. StreamEncoder#writeBytes()调用PrintStream#write(byte buf[], int off, int len)来刷新buffor if(autoFlush)

最重要的片段在上面。在这个流中,BufferedWriter似乎没有被调用。

票数 2
EN

Stack Overflow用户

发布于 2018-12-20 18:24:23

https://bugs.openjdk.java.net/browse/JDK-8025883描述了这个错误。

这在一个读取和解析二进制文件的程序中被我咬了一口,它执行了大量的System.out.printf()调用,这花费了更长的时间。

最后,我编写了一个助手类,它违反了流的契约,没有响应每个刷新请求:

代码语言:javascript
复制
class ForceBufferedOutputStream extends OutputStream {

    OutputStream out;
    byte[] buffer;
    int buflen;
    boolean haveNewline;
    private static final int bufsize=16384;

    public ForceBufferedOutputStream(OutputStream out) {
        this.out=out;
        this.buffer=new byte[bufsize];
        this.buflen=0;
        this.haveNewline=false;
    }
    @Override
    public void flush() throws IOException {
        if (this.haveNewline || this.buflen==bufsize) {
            out.write(buffer, 0, buflen);
            out.flush();
            this.buflen=0;
            this.haveNewline=false;
        }
    }
    @Override
    public void close() throws IOException {
        out.close();
    }

    @Override
    public void write(int b) throws IOException {
        buffer[buflen++]=(byte)b;
        if (b=='\n')
            this.haveNewline=true;
        if (buflen==bufsize)
            this.flush();
    }
}

然后使用new PrintStream(new ForceBufferedOutputStream(System.out))而不是System.out

我认为这是一个可怕的软件--正如所说的,它违反了flush()需要确保所有东西都被写入的契约,并且可以优化数组write调用。但是在我的例子中,运行时被从17分钟缩短到3:45,所以如果您需要一个复制/粘贴来加速快速和肮脏类型的程序,我希望它能有所帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44408151

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档