How do I get java to exit when piped to head

2020-02-26 04:58发布

问题:

I have a java process which prints out a lot of text. Sometimes I just want to see a bit of the text. With normal programs I can just do:

$ myprog | head

I'll just see 10 lines of output from myprog and it will exit immediately. But with java, if I do:

$ java MyClass | head

I get the first 10 lines of output, but the java process won't exit until it's done with all of its processing. It's like java doesn't care that stdout (System.out) is gone and the head process is dead and gone.

All other programs either exit silently, like cat:

$ cat /etc/group | head
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:

Or exit with a broken pipe error/exception, like python:

$ python -c 'while True: print "hi"' | head
hi
hi
hi
hi
hi
hi
hi
hi
hi
hi
Traceback (most recent call last):
  File "<string>", line 1, in <module>
IOError: [Errno 32] Broken pipe

How can get java to raise an exception when calling System.out.println() when I pipe output to something like head? I'd love to be able to do something like:

try {
    while(true) {
        System.out.println("hi");
    }
} catch(BrokenPipeException e) {
    // exit gracefully
}

回答1:

If you don't like the .checkError() method from Sascha's answer and would rather receive exceptions you can use

OutputStream stream = new FileOutputStream(FileDescriptor.out);

You lose the PrintStream specific functions. In my case, they weren't relevant and this approach was easier than building a bunch of hacky checks.

Note that this will not behave if you've redirected the System.out via System.setOut, as FileDescriptor.out will point to the original output descriptor, not your redirected one.



回答2:

i'm using checkError()

From PrintStream-API-Docu:

Unlike other output streams, a PrintStream never throws an IOException; instead, exceptional situations merely set an internal flag that can be tested via the checkError method.

so try somthing like this:

        while(!System.out.checkError()) {
            System.out.println("hi");
        }