如何检查PrintStream是否打开而不打印到它

时间:2018-01-05 19:06:06

标签: java io pipe

我有一个用Java编写的GUI程序,它使用System.out.println将数据输出到命令行。该数据旨在通过管道传输到另一个程序中。例如,我将通过head

管道该程序
$ java MyProgram | head -n10

我希望我的程序在管道损坏时退出:在这种情况下,这应该在MyProgram打印出十行文本后发生。

a similar question on this site,其中的解决方案效果相当不错;例如,我可以在自己的线程中运行以下命令:

while(!System.out.checkError()) {
    // sleep 100ms
}
System.exit(0);

问题是PrintStream.checkError()似乎只有在您尝试打印到流并失败后才会返回true。出于这个原因,我的程序实际上不会退出,直到它打印出 11个行文本:管道在前十后被破坏,但System.out继续返回{{1}直到我试图通过第十一行。

打印出额外的垃圾'为了在true上触发错误,行是不可能的,因为管道右侧的程序可能对它接收的数据非常敏感。

PrintStream中调用System.out.flush()PrintStream.checkError()没有影响,即使PrintStream的源代码表明它应该调用该类中的私有ensureOpen方法

如何在不打印任何内容的情况下可靠地测试System.out是否打开?

'真实世界'例如:假设我有一些程序consumer接受命令行输入并对其执行某些操作。某些输入会使consumer无声地失败。由于consumer的输入有时很长而且深奥,我在Java中编写了一个GUI程序InputProvider,我可以单击按钮并将相应的命令打印到stdout。如果我将InputProvider的输出传输到consumer,那么我就能够以图形方式控制consumer

不幸的是,InputProvider似乎没有办法在consumer关闭时通知用户,除非尝试写入consumer并获得某种异常。

2 个答案:

答案 0 :(得分:2)

我认为你不能用Java解决这个问题。 System.out之前没有任何问题,直到你写信给它失败。另一个进程(head)已经结束,但Java进程无法知道。

所以我认为你有两个选择。

  1. 不要使用管道来head但是限制Java代码中的输出 - 然后你就知道何时停止
  2. 接受最后一行将失败并正确处理异常

答案 1 :(得分:1)

尝试为系统设置新流,以便您能够检查该流是否已关闭:OutputStream output = new FileOutputStream("c:\\data\\system.out.txt");PrintStream printOut = new PrintStream(output);。然后在此处设置:System.setOut(printOut);并在if中查看if(printOut.checkError())