Java + Eclipse: Synchronize stdout and stderr
Asked Answered
C

5

12

I use Eclipse. When I have an application like this:

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

The output looks many times like this:

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

Is there a way to synchronize these two output streams? Of course without waiting a few milliseconds after the block of 20 times Hello World and waiting a few milliseconds after printing ERROR.

Chenopod answered 24/5, 2010 at 12:22 Comment(0)
I
8

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?

Inquiry answered 17/11, 2010 at 1:3 Comment(0)
A
7

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

Affiant answered 24/5, 2010 at 12:43 Comment(2)
"is it a byte stream or a character stream?". It is clearly a byte stream. The methods that write characters, strings, numbers, etc do implicit conversions to bytes using the JVM's default charset.Ultrasonic
@Stephen I was talking about it's client interface in java. PrintWriter allows for writing characters, OutputStream writes bytes, yet the interface provided by PrintStream writes both bytes and characters, but as you point out, if you write a string through the stream then you'll get bytes out the other end in the current default encoding. This is not a good thing and is an anomaly of the early jdk 1.0 design before i18n was complete, i18n brought a clear distinction between writing bytes and writing characters. Please see the second link for more on this.Affiant
P
3

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

Paracelsus answered 24/5, 2010 at 12:23 Comment(0)
S
1

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

Sparse answered 26/5, 2018 at 16:47 Comment(0)
I
0

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

Incompatible answered 8/5, 2012 at 20:32 Comment(1)
This horrible hack of a solution actually works. In intellij, its more like sleep 1000 - 500 wasnt enough. Useful for non-production/debugging environmentsWonderment

© 2022 - 2024 — McMap. All rights reserved.