我无法读取程序的完整输出,有时它会挂起接口,无法完全编译。在netbeans的输出控制台中,它显示完整的输出,但不在jtextarea中。
帮我先执行cmd中的命令(命令提示符),然后从cmd读取文本区域的输出。
在cmd中,命令执行迅速,结果完整。但我不知道如何从cmd中获得结果。
这是我的代码:
String line;
String [] cmds={"xyz.exe","--version"};
try{
Process p =Runtime.getRuntime().exec(cmds);
p.waitFor();
int val=p.exitValue();
if(val==0)
{
b1.setForeground(Color.green);
InputStream ins = p.getInputStream();
InputStreamReader insr = new InputStreamReader(ins);
BufferedReader br = new BufferedReader(insr);
while ((line = br.readLine()) != null) {
System.out.println( line);
t1.setText( line);
}
} else if(val==1)
{
b1.setForeground(Color.red);
InputStream error = p.getErrorStream();
InputStreamReader isrerror = new InputStreamReader(error);
BufferedReader bre = new BufferedReader(isrerror);
while ((line = bre.readLine()) != null) {
t1.setText(line);
}
}
} catch(IOException e){
System.out.println("error");
e.printStackTrace();
} catch (InterruptedException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
我看到的问题是这个。您正在尝试执行一个程序,但在程序执行完毕之前,您不会读取程序的输出流(即Process的getInputStream())。因此,如果您的子进程碰巧有很多输出,并且耗尽了缓冲区,那么子进程将被阻塞。
因此,为了解决您的问题,您需要在子流程仍在执行时绝对读取输入流和错误流,以避免子流程被阻塞。你可以使用阻塞IO,这意味着你需要单独的线程来服务输出流和错误流,也可以使用非阻塞IO,你可以使用1个线程来持续监控输出流&要读取的数据的错误流。
Java.lang.Process上的Java文档显示
由于一些本地平台仅为标准输入和输出流提供有限的缓冲区大小,因此未能及时写入子流程的输入流或读取子流程的输出流可能会导致子流程阻塞,甚至死锁。
import java.io.*;
import java.nio.channels.*;
import java.nio.*;
public static void nioExecute() throws Exception {
Process p = Runtime.getRuntime().exec("javac");
ReadableByteChannel stdoutChannel = Channels.newChannel(p.getInputStream());
ReadableByteChannel stderrChannel = Channels.newChannel(p.getErrorStream());
ByteBuffer buffer = ByteBuffer.allocate(1000);
StringBuilder stdOut = new StringBuilder();
StringBuilder stdErr = new StringBuilder();
while(stdoutChannel.isOpen() || stderrChannel.isOpen()) {
buffer.clear();
if(stderrChannel.isOpen()) {
int bytesRead = stderrChannel.read(buffer);
if(bytesRead>0) stdErr.append(new String(buffer.array(),0,bytesRead));
if(bytesRead==-1) stderrChannel.close();
}
buffer.clear();
if(stdoutChannel.isOpen()) {
int bytesRead = stdoutChannel.read(buffer);
if(bytesRead>0) stdOut.append(new String(buffer.array(),0,bytesRead));
if(bytesRead==-1) stdoutChannel.close();
}
Thread.sleep(100);
}
if(stdOut.length()>0) System.out.println("STDOUT: " + stdOut);
if(stdErr.length()>0) System.out.println("STDERR: " + stdErr);
}