我正在尝试开发一个读取外部程序标准输出的类(使用Process,Runtime.getRuntime()。exec(cmdLine,env,dir)的实例)。 程序在过程中接受用户输入,并且在给出有效输入之前不会继续;这似乎导致我试图读取其输出的方式出现问题:
egm.execute(); // run external the program with specified arguments
BufferedInputStream stdout = new BufferedInputStream(egm.getInputStream());
BufferedInputStream stderr = new BufferedInputStream(egm.getErrorStream());
BufferedOutputStream stdin = new BufferedOutputStream(egm.getOutputStream());
int c; //standard output input stream
int e; //standadr error input stream
while((c=stdout.read()) != -1) //<-- the Java class stops here, waiting for input?
{
egm.processStdOutStream((char)c);
}
while((e=stderr.read()) != -1)
{
egm.processStdErrStream((char)e);
}
//...
如何解决此问题,以便程序接收有效输入并继续?解决这个问题的任何帮助都会很棒!
答案 0 :(得分:7)
你有同时使用程序的stdout和stderr来避免阻塞场景。
有关详细信息,请参阅this article,特别注意在单独的线程中捕获stdout / err的StreamGobbler
机制。这对于防止阻塞至关重要,如果您不能正确执行,则会导致大量错误!
答案 1 :(得分:2)
在这种情况下,你应该有单独的Threads读取InputStream和ErrStream。
你也可能想做类似的事情:
public void run() {
while( iShouldStillBeRunning ) {
int c;
while( stdout.available() > 0 && ((c=stdout.read()) != -1)) {
egm.processStdOutStream((char)c);
}
Thread.sleep(100);
}
}
因为在输入之前您将被stdout.read()
阻止。
答案 2 :(得分:1)
首先,如果它正在写入错误流并且已经耗尽缓冲区,则可能会阻塞 - 在输出流完全完成之前,您不会从错误流中读取。
接下来,您说在此过程中需要用户输入 - 您是否通过写入stdin
向提供任何用户输入?如果它正在等待输入,您应该适当地写入stdin
并刷新它。
答案 3 :(得分:0)
当你试图运行它时,你没有在你的问题中说出实际发生了什么。请更新详细说明发生的情况,以及您希望发生的情况。告诉我们命令是什么的奖励点。
另外,这是UNIX / Linux还是Windows?如果这是UNIX / Linux(或其他一些POSIX平台),出于安全原因,程序可能会在/ dev / console而不是/ dev / stdin上查找输入。
答案 4 :(得分:0)
为了其他人寻找这类问题的解决方案的好处,我只想补充说我有一个非常类似的问题。但在我的情况下,程序也在等待一行输入。因此需要涉及三个线程来异步处理所有三个通道。
不写入输出(即执行程序的标准输入)导致输入(即来自执行程序的输出)不被完全捕获。写信给它会拖延这个过程。
解决方案是Jon Skeet的三个字:“并冲洗它”。添加刷新后,没有挂起。谢谢!