2012-09-21 48 views
9

有没有一种简单的方法来读取未缓冲的子进程的输出?我试图从Java调用一个C程序,但显然它是在连接到管道时进行标准块缓冲,并且只有在连接到控制台时才进行线路缓冲。我无法修改C程序。windows上无缓冲的子进程stdout

也许有一种方法来愚弄程序认为它连接到控制台?也可以在Linux上使用的解决方案的奖励点。

+1

你可以打开一个SSH到同一台机器并运行它。我怀疑这样做并不简单。 –

+0

“行缓冲”发生在操作系统级别。例如,在Linux上,您可以使用“ioctl()”将您的终端设置为“原始模式”。也许你可以谷歌的“Java终端I/O”,“Java诅咒”或类似的关键字? – paulsm4

+0

我已经在互联网和SO上进行了彻底搜索。这似乎是一个常见问题,但我还没有找到Windows的一个解决方案 –

回答

-1

OK -

1)“行缓冲输入”是控制台模式的程序中常用的成语,可以追溯到最初的Unix和串行模式VTxx终端。 2)您可以读取“原始的,无缓冲的”I/O(一次一个按键,而不是一次一行),但细节与操作系统相关。无论你在需要做什么特定的操作系统,你几乎可以肯定可以来自Java。 3)听起来好像你希望能够在Windows键盘上拦截“向上箭头”键或“向下翻页”键。或许用于玩游戏或与控制台模式用户界面交互。

4)有几种选择。一,你不妨考虑是“机器人”的API,用于测试:

如果这还不够,请给究竟你想如何让您的Java详情程序与C程序进行交互(并阐明平台是否确实是Windows和DOS提示符)。

+0

我不需要原始输入,线路缓冲就足够了。我尝试了'Runtime.getRuntime().exec(command);''或'new ProcessBuilder(command).start();'执行C程序,然后'process.getInputStream()',但它给了我一个block-缓冲流。 –

-1

你可以使用

org.apache.commons.io.input.Tailer 
+0

不幸的是,写入文件几乎肯定也会被缓存。 –

+0

下面的评论中的用户说线路缓冲是好的。我们希望直接从可执行文件中重定向输出,而不是从java中输出,也许这很有效。 – user1569047

+0

我从来没有听说过Windows中做线缓冲的任何事情;通常,输出是块缓冲或无缓冲。无论如何,如果重定向到管道被块缓冲,重定向到文件几乎肯定也会被块缓冲。这不是Java问题,它与子流程中C运行时库的行为有关。 –

0

您是否尝试过使用环境变量BUF_1_ = 0重定向C输出到一个文件,然后从尾在java中另一个线程的文件吗?

+0

就我从Google搜索中可以看出的情况来看,这是一个提议的用于抑制glibc库中的缓冲的机制,但开发人员拒绝了它。你有更好的参考? (我用Visual Studio试过它,它似乎没有工作。) –

-1

做到这一点是使用线程读取输出的最好方法

我会做的是:使用可赎回(一个Runnable也将工作),我得从流程的输入(process.getInputStream( ))和我想要存储输出的输出。 StdErr也应该这样做。可以使用任何你喜欢的方式读取结果输出。

public Object call() throws IOException { 
     int bytesRead; 
     byte[] b = new byte [ this.maxBlockSize ]; 

     try { 
      while ((bytesRead = this.input.read (b)) != -1) { 
       this.output.write (b, 0, bytesRead); 
      } 
     } finally { 
      if (this.output != null) { 
       this.output.close(); 
      } 
     } 
     return null; 
    } 
+0

这并没有解决OP问题。输出缓冲在子进程中,而不是在父进程中。 –

+0

如果这样做,它是否因为在单独的线程中读取而被阻塞无关紧要。 – azl

+2

你错过了一点,那就是他需要立即输出子进程的输出,而不是在孩子的stdout缓冲区最终填满时的未来不确定时间。使读取非阻塞意味着他的程序可以在等待子进程时做其他工作,但它不能帮助它更快地获得输出。 (特别是,考虑子进程正在等待输入的情况,但是父进程在知道输入要发送之前需要看到输出;进程将会死锁。) –

1

这不是一个很好的解决方案,但运行时库可能不缓冲串行端口,所以,如果你绝望的话,你可以使用一个零调制解调器模拟器如com0com或其衍生物。