我有一个片段如下:
Process proc = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
String line = br.readLine();
现在在上面的代码中我确信该进程将始终具有在线输入,因此我没有使用任何类型的while循环或任何null检查。问题是readLine块。我知道的一个原因是,流没有数据要读取,因此readLine一直在等待。为了检查这一点,我删除了readLine并使用了read()函数,如下所示:
Process proc = Runtime.getRuntime().exec( command );
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
int a;
while((a=br.read())!=-1){
char ch = (char) a;
if(ch == '\n')
System.out.print("New line "+ch);
if(ch == '\r')
System.out.print("Carriage return "+ch);
System.out.print(ch);
}
令我惊讶的是,这段代码工作并打印出麻烦的新行和回车。现在我想知道为什么readLine块?数据可用,它由换行符终止。还有什么可能的原因?
注意:以上工作偶尔一次!也许一次出15次 注意:我也尝试使用ProcessBuilder,但行为相同。
更新: 所以我切换到ProcessBuilder然后我重定向了errorStream,现在当我执行process.getInputStream时,我立刻得到输入流和错误流,这很好。以下是摘录。
ProcessBuilder pb = new ProcessBuilder(command.split(" "));
pb..redirectErrorStream(true);
Process proc = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = br.readLine();
//Now I get both input and error stream.
我想区分我的错误流和输入流,但是使用这种方法它们都混乱了!关于这个的任何想法?
答案 0 :(得分:2)
您可以使用线程,以避免它。
像一个负责阅读的奴隶线程。这不会阻止你的课程进度。
答案 1 :(得分:1)
我认为问题不在于标准错误是阻塞,而是标准输出阻塞导致您调用的应用程序阻塞。
标准输出通常是缓冲的。如果您调用的进程写入的标准输出少于缓冲区大小,那么一切都很好,它可以达到写入标准错误的代码。如果进程填充缓冲区,则其写入标准输出的尝试将被阻止,并且它将永远不会到达写入标准错误的位置。
这可能是您偶尔看到它工作的原因 - 有时标准输出不会填充缓冲区。这也可能是它长时间工作的原因:最终写入标准输出超时。
作为演示,这个简单的过程总是像你在我的Windows 8机器上描述的那样阻塞:
public class Proc {
public static void main(String[] args) {
for(int i=0;i<1000;i++) {
System.out.print("More data ");
}
System.out.println();
System.err.println("An error line");
}
}
答案 2 :(得分:0)
因此,为了避免错误流和输入流合并,只需删除该行
pb.redirectErrorStream(true);
因为如java doc所述:
如果此属性为true,则此对象的start()方法随后启动的子进程生成的任何错误输出将与标准输出合并,以便可以使用Process.getInputStream()读取这两个错误输出方法。这使得更容易将错误消息与相应的输出相关联。初始值为false。
通过调用pb.redirectErrorStream(true);
,您正在合并两个输出。
答案 3 :(得分:0)
getErrorStream声明如下 返回连接到子进程的错误输出的输入流。该流获取从此Process对象表示的进程的错误输出中传输的数据。 如果使用ProcessBuilder.redirectError或ProcessBuilder.redirectErrorStream重定向子进程的标准错误,则此方法将返回空输入流。
并且ReadLine声明如下 读一行文字。一条线被认为是由换行符('\ n'),回车符('\ r')或回车符中的任何一个终止,后面紧跟换行符。
基于提供给API的解释。 readline无限期地等待获取换行符或回车符,因为processbuilder返回NULL,这就是readLine终止为止的原因。