2012-02-05 73 views
10

在Java中,我注意到有时,System.err语句在System.out语句之前首先打印,尽管后者在我的代码中先于前者出现。为什么?我很好奇。为什么有时会首先打印System.err语句?

+0

从1.02我一直坚持使用'System.err'当我正在黑客正是这个原因。不知道Java的更新版本的行为,因为我没有测试它。 – 2012-02-05 03:35:39

回答

17

通常,System.out是一个缓冲输出流,因此文本在刷新到目标位置之前累积。这可以显着提高打印大量文本的应用程序的性能,因为它最大限度地减少了必须进行的昂贵系统调用的次数。但是,这意味着文本并不总是立即显示,并且可能比写入文本晚得多。

System.err另一方面,通常不会被缓冲,因为需要立即打印错误消息。这是慢的,但直觉是错误信息可能是时间关键的,所以程序放缓可能是合理的。根据the Javadoc for System.err

典型地,这流对应于显示输出或由主机环境或用户指定的另一个输出目的地。 按照惯例,即使主输出流(即变量out的值)已被重定向到文件或其他目的地,该输出流也可用于显示错误消息或其他应立即引起用户注意的信息通常不会持续监控。

(我的重点)

然而,作为一个结果,发送到System.out旧数据可能较新System.err消息后显示出来,因为旧的缓存的数据后刷新比消息发送到System.err。例如该序列的事件:

  • “你好,”缓冲至System.out
  • “PANIC”被直接发送到System.err并立即打印。
  • “世界!”缓冲至System.out,并且将缓冲的数据被打印

将导致输出

PANIC 
Hello, world! 

即使Hello印刷到System.outPANIC之前被印到System.err

希望这会有所帮助!

+0

只是出于好奇:Java在与终端连接时是否与C使用stdout相同的保证?即每次写入换行符时我们都会刷新缓冲区? – Voo 2012-02-05 01:56:42

+0

@ Voo-我只是看着Javadoc,并没有出现这种类型的东西。 – templatetypedef 2012-02-05 01:57:57

+0

'PrintStream'被实现在几乎所有东西之后刷新(我认为你可以直接'写入'而不是)。 – 2012-02-05 03:34:12

2

它与缓冲和优先级有关。据推测,爪哇(如C和C衍生物)不缓冲System.errstderr等,不像System.outstdout,等等。这样,系统可以确保你最有可能得到任何相关的错误消息,即使它出于某种原因必须降低标准输出。

Wikipedia

这是可接受的和正常标准输出和标准错误将被引导到相同的目的地,诸如文本终端。消息以与程序写入相同的顺序出现,除非涉及缓冲。 (例如,常见情况是标准错误流未缓冲,但标准输出流是行缓冲的;在这种情况下,稍后写入标准错误的文本可能会在较早时出现在终端上,如果标准输出流的缓冲区不是还没有完整)。

+0

我从来没有对任何流的重点心脏..这是如何工作?我会用简单的缓冲解释。 – Voo 2012-02-05 01:54:57

+0

只是华丽的语言问题。固定更技术:) – 2012-02-05 01:58:16

相关问题