如何让 java 在通过管道传送到头部时退出

2022-09-02 22:19:37

我有一个java进程,可以打印出很多文本。有时我只想看一些文字。使用普通程序,我可以只做:

$ myprog | head

我只看到来自myprog的10行输出,它将立即退出。但是使用java,如果我这样做:

$ java MyClass | head

我得到了前10行输出,但是java进程在完成所有处理之前不会退出。这就像java不在乎stdout(System.out)消失了,而head进程已经死了。

所有其他程序要么默默退出,要么像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:

或者退出时出现管道损坏错误/异常,如 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

如何让java在调用System.out.println()时引发异常,当我通过管道将输出连接到类似head的东西时?我希望能够做这样的事情:

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

答案 1

我正在使用checkError()

来自 PrintStream-API-Docu

与其他输出流不同,PrintStream从不抛出IOException;相反,特殊情况只是设置一个可以通过checkError方法测试的内部标志。

所以试试这样的东西:

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

答案 2

如果您不喜欢Sascha答案中的方法,并且宁愿收到异常,则可以使用.checkError()

OutputStream stream = new FileOutputStream(FileDescriptor.out);

您将失去特定的功能。在我的情况下,它们并不相关,这种方法比构建一堆黑客检查更容易。PrintStream

请注意,如果您已重定向 via ,则不会这样做,因为这将指向原始输出描述符,而不是重定向的输出描述符。System.outSystem.setOutFileDescriptor.out