Java 如何在不打印的情况下检查打印流是否打开

Java 如何在不打印的情况下检查打印流是否打开,java,io,pipe,Java,Io,Pipe,我有一个用Java编写的GUI程序,它使用System.out.println将数据输出到命令行。数据打算通过管道传输到另一个程序中。例如,我将通过管道将程序传送到头部: $ java MyProgram | head -n10 我希望我的程序在管道断开时退出:在这种情况下,这应该在MyProgram打印出十行文本后发生 有,并且给出的解决方案相当有效;例如,我可以在自己的线程中运行以下内容: while(!System.out.checkError()) { // sleep 100

我有一个用Java编写的GUI程序,它使用
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我认为这并不正确