SOLVED:
HovecraftFullOfEels发现了我的错误 . 请参阅下面的答案评论 . 我应该调用start()时在Thread对象上调用run() . 在我的原始程序中,这意味着它在stderr上被阻止,直到程序退出然后立即获得stdout .
UPDATE:
根据要求,我已经制作了一个最小的例子 . 这是制作人:
package producer;
public class Producer {
public static void main(String[] args) throws InterruptedException {
for (int i=0; i<10; i++) {
System.out.println(i);
System.out.flush();
Thread.sleep(1000);
}
}
}
这是消费者:
package consumer;
import java.io.IOException;
import java.io.InputStream;
public class Consumer {
static class Dumper extends Thread {
InputStream r;
boolean print;
Dumper(InputStream r, boolean print) {
this.r = r;
this.print = print;
}
@Override
public void run() {
int c;
try {
while ((c = r.read()) != -1) {
if (print) System.out.print((char)c);
}
r.close();
} catch (IOException ex) {}
}
}
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec("java -jar C:\\Users\\millerti\\Documents\\NetBeansProjects\\Producer\\dist\\Producer.jar");
new Dumper(p.getErrorStream(), false).run();
new Dumper(p.getInputStream(), true).run();
p.waitFor();
}
}
预期的行为:由于 生产环境 者刷新其输出并且消费者完全没有缓冲,消费者应该实时获得 生产环境 者的输出 .
观察到的行为:消费者只有在 生产环境 者完成时才会立即收到 生产环境 者的输出 .
Original post :
我正在与Windows应用程序上的另一个开发人员合作 . 她编写了一个C程序(我们可以修改),它执行媒体转换并将进度消息(百分比)打印到stdout . 我正在用Java编写图形前端,我希望我的程序捕获这些消息并更新GUI元素 .
相关的C程序代码如下所示:
printf ("progress_msg: %d%%\n", currentProgress);
fflush(stdout);
在Java程序中,我使用 Runtime.getRuntime().exec()
来运行C程序并抓取原始的InputStream对象,用于解析stdout流的C程序's stdout and stderr. (The stderr is just being thrown away by another thread.) I',查找这些消息(好吧,我是,使用BufferedReader,但是现在,我'm trying to debug this, so I'm直接与低级InputStream字节源通信 . )
问题是虽然Java端没有缓冲(我知道)并且C程序中有 fflush
,但只有当C程序完成时才会出现stdout文本 . 当我从命令提示符运行它时,这与消息不同,消息按预期逐渐出现 .
那么清楚,有_654604知道吗?如果是这样,有没有办法把它关掉? Windows中的 fflush(stdout)
无法按预期方式工作吗?什么是正确的Windows等价物?
谢谢 .
注意:我找到了两个相关的stackoverflow,但他们没有回答这个问题 . 特别是,我们可以修改C程序,没有行缓冲,我们正在进行适当的刷新(据我们所知) . 见I want realtime output of my Runtime.getRuntime().exec()和Unbuffered subprocess stdout on windows .
1 回答
我的一个疯狂的猜测,但你说:
我再次猜测,因为你遗漏了重要的细节,所有代码,但如果你的前端是一个Swing GUI,那么你所描述的症状表明你正在尝试获取有关Swing事件线程的所有信息 . 如果这是一个Swing应用程序,解决方案是确保在后台线程(例如SwingWorker提供的线程)中读取Stream的输出,以确保缓冲您正在读取的数据,然后以线程安全的方式在GUI中显示它(再次使用SwingWorker,尤其是其发布/进程方法对) .
为了获得更好的帮助,请向我们提供更好的信息和代码,最好是一小部分,实际上是最小的,我们可以运行,测试和改进 .
Edit
我的测试程序: