Java 如何在不打印的情况下检查打印流是否打开
我有一个用Java编写的GUI程序,它使用Java 如何在不打印的情况下检查打印流是否打开,java,io,pipe,Java,Io,Pipe,我有一个用Java编写的GUI程序,它使用System.out.println将数据输出到命令行。数据打算通过管道传输到另一个程序中。例如,我将通过管道将程序传送到头部: $ java MyProgram | head -n10 我希望我的程序在管道断开时退出:在这种情况下,这应该在MyProgram打印出十行文本后发生 有,并且给出的解决方案相当有效;例如,我可以在自己的线程中运行以下内容: while(!System.out.checkError()) { // sleep 100
System.out.println
将数据输出到命令行。数据打算通过管道传输到另一个程序中。例如,我将通过管道将程序传送到头部
:
$ java MyProgram | head -n10
我希望我的程序在管道断开时退出:在这种情况下,这应该在MyProgram
打印出十行文本后发生
有,并且给出的解决方案相当有效;例如,我可以在自己的线程中运行以下内容:
while(!System.out.checkError()) {
// sleep 100ms
}
System.exit(0);
问题在于,PrintStream.checkError()
似乎只有在您尝试打印到流中失败后才会返回true
。出于这个原因,我的程序实际上直到打印出11行文本才退出:管道在前10行之后断开,但是System.out
继续返回true
,直到我尝试通过第11行
打印额外的“垃圾”行以触发PrintStream
上的错误是不可能的,因为管道右侧的程序可能对其接收的数据非常敏感
在循环内调用System.out.flush()
对PrintStream.checkError()
没有任何影响,即使PrintStream
的源代码表明它应该调用该类中的私有ensureOpen
方法
如何可靠地测试System.out
是否已打开而不向其打印任何内容
“真实世界”示例:假设我有一个程序
使用者
,它接收命令行输入并对其进行处理。某些输入将调用消费者
以无提示地失败。由于消费者的输入有时又长又难,我用Java编写了一个GUI程序InputProvider,在那里我可以单击按钮并将相应的命令打印到stdout。如果我将InputProvider
的输出导入consumer
,那么我就能够以图形方式控制consumer
不幸的是,
InputProvider
似乎无法在消费者
关闭时通知用户,除非尝试写入消费者并获得某种异常。尝试为系统设置一个新流,这样您就可以检查该流是否关闭:OutputStream output=new FileOutputStream(“c:\\data\\system.out.txt”)代码>和<代码>打印流打印输出=新打印流(输出)代码>。然后在这里设置:System.setOut(打印输出)代码>和在if中,您可以检查if(printOut.checkError())
尝试为系统设置一个新流,这样您就可以检查该流是否关闭:OutputStream output=new FileOutputStream(“c:\\data\\system.out.txt”)代码>和<代码>打印流打印输出=新打印流(输出)代码>。然后在这里设置:System.setOut(打印输出)代码>和内部的if,您可以检查if(printOut.checkError())
我认为您无法用Java解决这个问题。System.out没有任何问题,直到您写入它并失败。另一个进程(head
)结束了,但Java进程不知道这一点
所以我认为你有两个选择
不要使用管道来head
,而是限制Java代码中的输出-这样您就知道何时停止
接受最后一行将失败并适当处理异常
我认为用Java无法解决这个问题。System.out没有任何问题,直到您写入它并失败。另一个进程(head
)结束了,但Java进程不知道这一点
所以我认为你有两个选择
不要使用管道来head
,而是限制Java代码中的输出-这样您就知道何时停止
接受最后一行将失败并适当处理异常
这听起来像是一个错误。您需要澄清为什么您认为第11行输出失败是不好的。所有这些发生的基本机制都是在操作系统中,而不是在Java中,并且在您尝试编写之前,断管指示不会发生。@JimGarrison我认为这不是XY问题。当管道另一侧的程序关闭时,我希望输入程序关闭。也许head
示例具有误导性。至少,我希望我的输入程序能够判断其他程序是否已退出。两者之间唯一的通信机制是管道,它对应于System.out
的状态。正如我所说,如果没有其他通信通道,这是不可能的。该管道由操作系统处理,在尝试写入管道之前,不会发生错误。换言之,试图使用断裂的管道进行流量控制是一种不正确的方法,无法使其发挥作用。您能否详细说明一下,您如何说管道在10行之后断裂?通过查看输出线,您似乎有办法知道管道是否损坏。第11行出现在输出中这一事实意味着IO在此之前是完整的。@svasa第11行没有出现在输出中,但是MyProgram
没有退出。在本例中,这不是问题,因为我可以看出head
已经退出,因为它不再生成输出。但是,对于另一个没有直接打印其输入的程序,我可能无法判断该程序是否已退出。这听起来像是一个错误。您需要澄清为什么您认为第11行输出失败是不好的。所有这些发生的底层机制都是在操作系统中,而不是在Java中,并且在您尝试编写之前,断管指示不会发生。@JimGarrison我认为这并不正确