Java + Eclipse: Synchronize stdout and stderr

为君一笑 提交于 2019-11-30 18:43:12

Believe it or not, flushing is not a solution here....

If a stream leads to "an abstraction provided by the underlying operating system" (e.g. a disk drive or console) then remaining bytes "are passed to the operating system for writing; it does not guarantee that they are actually written..." (see the OutputStream documentation). The key here is that the OS can handle flushes from different streams in different orders if it so chooses.

I just had this happen in my program. I had an error message appear between two normal message, both of which had flushed before the error message did.

So the question remains, is there a built-in way to synchronize two streams? Or do we have to handle that manually?

mdma

For "serious" use, I prefer not writing directly to System.out/System.err, since it hard-codes the destination, and it also it uses the rather quirky PrintStream (is it a byte stream or a character stream?). If you wrap the output streams in your own PrintWriter, you can then set it to flush automatically - the second argument in the constructor is 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

See

System.out and System.err are ordinary PrintStream objects (which provide a flush() method), so try System.out.flush() and System.err.flush().

AFAIK there is no reliable way to force a sync on 2 unrelated streams.

A workaround is to use only one stream: e.g. use System.setErr() to redirect out to err, so that everything is printed on the error stream:

System.setErr(System.out);

Or the other way around via System.setOut()

System.setOut(System.err);

A downside of this is that it may change syntax-highlighting: e.g. some IDEs may highlight text on stderr and stdout differently

Robert Wolf

Add a flush followed by a Thread.sleep(1), 99.9% output order will be correct.

For example, this will display as expected.

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 );

The only drawback is the sleep for 1 millisecond, i.e. 1/1000 second

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!