【问题标题】:How to check whether a PrintStream is open without printing to it如何检查 PrintStream 是否打开而不打印到它
【发布时间】:2018-01-05 19:06:06
【问题描述】:

我有一个用 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 继续返回 true 直到我尝试管道通过第十一条线。

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

在循环内调用System.out.flush()PrintStream.checkError() 没有影响,尽管PrintStream 的源代码表明它应该调用该类中的私有ensureOpen 方法。

如何可靠地测试System.out 是否打开而不打印任何内容?


“真实世界”示例:假设我有一些程序consumer 接受命令行输入并对其进行处理。某些输入将调用consumer 静默失败。由于consumer 的输入有时很长而且很深奥,我用Java 编写了一个GUI 程序InputProvider,我可以在其中单击按钮并将相应的命令打印到stdout。如果我将InputProvider 的输出通过管道传输到consumer,那么我就能够以图形方式控制consumer

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

【问题讨论】:

  • 这听起来像XY Problem。你需要澄清为什么你认为在第 11 行输出失败是不行的。所有这一切发生的底层机制是在操作系统中,而不是在 Java 中,并且在您尝试编写之前不会发生损坏的管道指示。
  • @JimGarrison 我认为这不是 XY 问题。当管道另一侧的程序关闭时,我希望我的输入程序关闭。也许head 示例具有误导性。至少,我希望我的输入程序能够判断其他程序是否已经退出。两者通信的唯一机制是管道,对应System.out的状态。
  • 那么正如我所说,如果没有其他沟通渠道,这是不可能的。管道由操作系统处理,在您尝试写入管道之前不会发生错误。换句话说,尝试使用损坏的管道进行流量控制是一种不正确的方法,并且无法正常工作。
  • 你能详细说明一下,你怎么能说 10 行后管道坏了?看来您有办法通过查看输出行来了解管道是否损坏。第 11 行出现在输出中的事实意味着 IO 在此之前是完整的。
  • @svasa 第 11 行没有出现在输出中,但 MyProgram 没有退出。在这种情况下,这不是问题,因为我可以看出head 已经退出,因为它不再产生输出。但是,对于另一个不直接打印其输入的程序,我可能无法判断该程序已经退出。

标签: java io pipe


【解决方案1】:

我认为您无法在 Java 中解决此问题。 System.out 没有任何问题,直到您写入它并且它失败了。另一个进程 (head) 结束了,但 Java 进程不知道。

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

  1. 不要使用管道连接到head,而是在 Java 代码中限制输出 - 这样你就会知道何时停止
  2. 接受最后一行将失败并适当处理异常

【讨论】:

    【解决方案2】:

    尝试为系统设置一个新流,这样您就可以检查该流是否已关闭:OutputStream output = new FileOutputStream("c:\\data\\system.out.txt");PrintStream printOut = new PrintStream(output);。然后在这里设置:System.setOut(printOut); 和里面如果你可以检查if(printOut.checkError())

    【讨论】:

      猜你喜欢
      • 2013-08-08
      • 1970-01-01
      • 2011-11-09
      • 1970-01-01
      • 1970-01-01
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 2010-12-08
      相关资源
      最近更新 更多