Java + Eclipse:同步stdout和stderr

时间:2010-05-24 12:22:10

标签: java eclipse synchronization stdio

我使用Eclipse。当我有这样的应用程序时:

write 20 times 'Hello World\n' to stdout
write 'ERROR\n' to stderr
write 5 times 'Hello  World\n' to stdout

输出看起来很多次:

Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
...
Hello World
Hello World
Hello World
ERROR

有没有办法同步这两个输出流?当然,无需等待20次Hello World的块后几毫秒,并在打印ERROR后等待几毫秒。

5 个答案:

答案 0 :(得分:7)

信不信由你,冲洗不是解决方案......

如果流导致“底层操作系统提供的抽象”(例如磁盘驱动器或控制台),那么剩余的字节“将被传递给操作系统进行写入;它不能保证它们实际被写入.. 。“(见the OutputStream documentation)。这里的关键是操作系统可以根据不同的顺序处理来自不同流的不同流的刷新。

我刚刚在我的程序中发生过这种情况。我在两条正常消息之间出现了一条错误消息,这两条消息都在错误消息之前刷新了。

所以问题仍然存在,是否有内置的方法来同步两个流?或者我们必须手动处理吗?

答案 1 :(得分:6)

对于“严肃”使用,我不希望直接写入System.out/System.err,因为它会对目标进行硬编码,而且它也会使用相当古怪的PrintStream(它是字节流还是字符流?)。如果将输出流包装在自己的PrintWriter中,则可以将其设置为自动刷新 - 构造函数中的第二个参数为auto-flush

E.g。

PrintWriter out = new PrintWriter(System.out, true);
PrintWriter err = new PrintWriter(System.err, true);

out.println("Hello world");
//this will flush after writing the end of line

答案 2 :(得分:2)

System.out和System.err是普通的PrintStream对象(提供flush()方法),所以请尝试System.out.flush()System.err.flush()

答案 3 :(得分:1)

AFAIK没有可靠的方法强制同步2个不相关的流。

解决方法是仅使用一个流:例​​如使用System.setErr()重定向到错误,以便在错误流上打印所有内容:

System.setErr(System.out);

或者通过System.setOut()

反过来
System.setOut(System.err);

这样做的缺点是它可能会改变语法高亮:例如某些IDE可能会以不同的方式突出显示stderr和stdout上的文本

答案 4 :(得分:0)

添加一个刷新后跟一个Thread.sleep(1),99.9%的输出顺序是正确的。

例如,这将按预期显示。

System.out.println( "stdout 1" ); System.out.flush(); Thread.sleep( 1 );
System.err.println( "stderr 1" ); System.err.flush(); Thread.sleep( 1 );
System.out.println( "stdout 2" ); System.out.flush(); Thread.sleep( 1 );
System.err.println( "stderr 2" ); System.err.flush(); Thread.sleep( 1 );

唯一的缺点是睡眠时间为1毫秒,即1/1000秒