[英]BufferedReader.readLine blocks my program but BufferedReader.read() reads properly
我有一个片段如下:
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.
我想区分我的错误流和输入流,但是使用这种方法它们都混乱了! 有什么想法吗?
您可以使用线程,以避免它。
像一个负责阅读的奴隶线程。 这不会阻止您的计划进度。
我认为问题不在于标准错误是阻塞,而是标准输出阻塞导致您调用的应用程序阻塞。
标准输出通常是缓冲的。 如果您调用的进程写入的标准输出少于缓冲区大小,那么一切都很好,它可以达到写入标准错误的代码。 如果进程填充缓冲区,则其写入标准输出的尝试将被阻止,并且它将永远不会到达写入标准错误的位置。
这可能是您偶尔看到它工作的原因 - 有时标准输出不会填充缓冲区。 这也可能是它在很长一段时间后工作的原因:最终写入标准输出超时。
作为演示,这个简单的过程总是像你在我的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");
}
}
因此,为避免获取错误流和输入流合并,只需删除行pb.redirectErrorStream(true);
因为正如java doc中所述:
如果此属性为true,则此对象的start()方法随后启动的子进程生成的任何错误输出将与标准输出合并,以便可以使用Process.getInputStream()方法读取这两者。 这使得更容易将错误消息与相应的输出相关联。 初始值为false。
通过调用pb.redirectErrorStream(true);
你正在合并两个输出。
getErrorStream声明以下内容返回连接到子进程的错误输出的输入流。 该流获取从此Process对象表示的进程的错误输出中传输的数据。 如果使用ProcessBuilder.redirectError或ProcessBuilder.redirectErrorStream重定向子进程的标准错误,则此方法将返回空输入流。
并且ReadLine声明以下内容读取一行文本。 一条线被认为是由换行符('\\ n'),回车符('\\ r')或回车符中的任何一个终止,后面紧跟换行符。
基于提供给API的解释。 readline无限期地等待获取换行或回车,因为processbuilder返回NULL,这就是readLine为此终止的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.