【问题标题】:System.out not flushingSystem.out 不刷新
【发布时间】:2016-10-29 03:17:11
【问题描述】:

我有一个 java 应用程序,它通过读取 System.in 的扫描仪获取输入,并通过 System.out 提供输出。扫描仪始终处于活动状态,如果不通过终端使用 Ctrl+C 或在 IDE 中结束进程,它不会终止。

我遇到了一些让我相信 System.out 没有正确刷新的行为。

在我的代码中有以下几行:

System.out.print(",\\" + '\n');
System.out.print("     " + someString); 

(someString 不包含换行符)

当我通过终端执行此代码时,空格和 someString 不会打印到终端。但是在我的 IDE 控制台中,它是。 (智能)

如果我将第二条语句更改为 println 而不是 print,它可以正常工作,但它确实在代码的一次执行和下一次执行之间添加了一个新行,这在此处不可行。 (也许我可以用回车做点什么?)

这听起来很像输出没有被刷新,因为它唯一的 System.out.print 有问题。但是,在 print 语句之后添加 System.out.flush() 不会导致它打印。

【问题讨论】:

  • 我不太确定问题是什么,但System.out 没有指定它的自动刷新行为;所以这取决于实施。显然,在您的特定设置中,IntelliJ 和任何 JAVA_HOME 设置(猜测用法)不同。
  • 可能是这样。我在 windows 和 linux 电脑上都试过了,同样的问题,它们都有相同版本的 JDK。
  • @Sudom82 您是否尝试在我的回答中添加 '\r\n' ?

标签: java system.out


【解决方案1】:

这听起来很像输出没有被刷新,因为它唯一的System.out.print 有问题。

通常System.outSystem.err 配置不同。 (System.err 通常不被缓冲,System.out 通常被缓冲。)但是,javadocs 没有指定任一流的刷新行为。这可以解释(真实)控制台和在 IDE 中运行之间的行为差​​异。

有关信息,以下是 Java 8 中流的初始化方式:

    FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
    FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
    FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
    setIn0(new BufferedInputStream(fdIn));
    setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
    setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));

private static PrintStream  ewPrintStream(FileOutputStream fos, String enc) {
   if (enc != null) {
        try {
            return new PrintStream(new BufferedOutputStream(fos, 128),
                                   true, enc);
        } catch (UnsupportedEncodingException uee) {}
    }
    return new PrintStream(new BufferedOutputStream(fos, 128), true);
}

如您所见,System.out 被初始化为已启用自动刷新的缓冲。


但是,在 print 语句之后添加System.out.flush() 不会导致它打印。

你确定吗? flush() 应该刷新任何缓冲的输出。

我认为问题实际上出在其他地方;例如printflush 呼叫没有发生......出于某种原因。


您的一些问题也可能是由于以下原因:

System.out.print(",\\" + '\n');

正如@javaguy 指出的那样,换行符是平台特定的行分隔符。在某些平台上,控制台需要不同的东西。告诉控制台进行换行的最简单的平台无关方法是:

System.out.println(",\\");

或者把它们放在一起:

System.out.println(",\\");
System.out.print("     " + someString); 
System.out.flush();   // This is necessary ... and should work.

【讨论】:

  • 我已经验证 System.out.flush() 是通过代码覆盖工具调用的。不过,我会仔细检查一下。
  • 代码覆盖率工具不会给出正确答案。它会告诉您该方法在某处 被调用,而不是在您感兴趣的特定位置 调用它。 (例如,在编写换行符时会在后台调用 flush 方法。)
  • 好吧,我只对这一种方法进行了一次测试,我的代码覆盖率工具用 System.out.flush();正在执行,以及之前的行和之后的行。我可能会误解它,但如果是这样,我不知道如何。
  • 好吧,就像我说的,换行符会触发刷新……你正在输出一个换行符。弄清楚发生了什么的更好方法是使用调试器,并在 PrintStream.flush() 方法上设置断点。这将告诉您实际调用 flush() 的时间和地点。
  • 我会试试你的调试器建议。感谢大家的帮助。如果我弄清楚了,我会回来报告。
【解决方案2】:

假设您在 Windows 中运行程序,马车 return (\r) 和 line feed (\n) 一起需要添加打印 新行如下:

System.out.print(",\\" + '\r\n');
System.out.print("     " + someString); 

【讨论】:

  • 这不是重点。自动刷新基于换行符 ('\n') 字符的存在。
  • @StephenC 我认为他的问题是'someString 不包含换行符'(如果从终端运行),所以添加 \r\n 应该可以解决问题。
  • @javaguy 刚刚尝试了你的建议,假设那些应该是第 1 行的 \r\n 周围的双引号(否则会出现编译器错误)。不幸的是,它并没有解决问题。在调用另一个新行(通过 println 或 print('\n'))之前,如果有的话, someString 仍然不会打印。
【解决方案3】:

System.out.println() 执行后将光标置于下一行。所以你不需要添加“\n”。这可能就是为什么行之间有一行空格。

这样做:

System.out.println(",\\");
System.out.println("     " + someString); 

【讨论】:

  • 这确实打印了所有输出,但它在代码执行之间添加了一个空的新行,这对我来说不是一个好的选择。
猜你喜欢
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
  • 2019-10-14
相关资源
最近更新 更多