有没有一种简单的方法来读取未缓冲的子进程的输出?我试图从Java调用一个C程序,但显然它是在连接到管道时进行标准块缓冲,并且只有在连接到控制台时才进行线路缓冲。我无法修改C程序。windows上无缓冲的子进程stdout
也许有一种方法来愚弄程序认为它连接到控制台?也可以在Linux上使用的解决方案的奖励点。
有没有一种简单的方法来读取未缓冲的子进程的输出?我试图从Java调用一个C程序,但显然它是在连接到管道时进行标准块缓冲,并且只有在连接到控制台时才进行线路缓冲。我无法修改C程序。windows上无缓冲的子进程stdout
也许有一种方法来愚弄程序认为它连接到控制台?也可以在Linux上使用的解决方案的奖励点。
OK -
1)“行缓冲输入”是控制台模式的程序中常用的成语,可以追溯到最初的Unix和串行模式VTxx终端。 2)您可以读取“原始的,无缓冲的”I/O(一次一个按键,而不是一次一行),但细节与操作系统相关。无论你在需要做什么特定的操作系统,你几乎可以肯定可以来自Java。 3)听起来好像你希望能够在Windows键盘上拦截“向上箭头”键或“向下翻页”键。或许用于玩游戏或与控制台模式用户界面交互。
4)有几种选择。一,你不妨考虑是“机器人”的API,用于测试:
如果这还不够,请给究竟你想如何让您的Java详情程序与C程序进行交互(并阐明平台是否确实是Windows和DOS提示符)。
我不需要原始输入,线路缓冲就足够了。我尝试了'Runtime.getRuntime().exec(command);''或'new ProcessBuilder(command).start();'执行C程序,然后'process.getInputStream()',但它给了我一个block-缓冲流。 –
你可以使用
org.apache.commons.io.input.Tailer
不幸的是,写入文件几乎肯定也会被缓存。 –
下面的评论中的用户说线路缓冲是好的。我们希望直接从可执行文件中重定向输出,而不是从java中输出,也许这很有效。 – user1569047
我从来没有听说过Windows中做线缓冲的任何事情;通常,输出是块缓冲或无缓冲。无论如何,如果重定向到管道被块缓冲,重定向到文件几乎肯定也会被块缓冲。这不是Java问题,它与子流程中C运行时库的行为有关。 –
您是否尝试过使用环境变量BUF_1_ = 0重定向C输出到一个文件,然后从尾在java中另一个线程的文件吗?
就我从Google搜索中可以看出的情况来看,这是一个提议的用于抑制glibc库中的缓冲的机制,但开发人员拒绝了它。你有更好的参考? (我用Visual Studio试过它,它似乎没有工作。) –
做到这一点是使用线程读取输出的最好方法
我会做的是:使用可赎回(一个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;
}
这并没有解决OP问题。输出缓冲在子进程中,而不是在父进程中。 –
如果这样做,它是否因为在单独的线程中读取而被阻塞无关紧要。 – azl
你错过了一点,那就是他需要立即输出子进程的输出,而不是在孩子的stdout缓冲区最终填满时的未来不确定时间。使读取非阻塞意味着他的程序可以在等待子进程时做其他工作,但它不能帮助它更快地获得输出。 (特别是,考虑子进程正在等待输入的情况,但是父进程在知道输入要发送之前需要看到输出;进程将会死锁。) –
这不是一个很好的解决方案,但运行时库可能不缓冲串行端口,所以,如果你绝望的话,你可以使用一个零调制解调器模拟器如com0com或其衍生物。
你可以打开一个SSH到同一台机器并运行它。我怀疑这样做并不简单。 –
“行缓冲”发生在操作系统级别。例如,在Linux上,您可以使用“ioctl()”将您的终端设置为“原始模式”。也许你可以谷歌的“Java终端I/O”,“Java诅咒”或类似的关键字? – paulsm4
我已经在互联网和SO上进行了彻底搜索。这似乎是一个常见问题,但我还没有找到Windows的一个解决方案 –