我正在使用ProcessBuilder在Java中构建一个流程,如下所示:
ProcessBuilder pb = new ProcessBuilder() .command("somecommand", "arg1", "arg2") .redirectErrorStream(true); Process p = pb.start(); InputStream stdOut = p.getInputStream();
现在,我的问题如下:我想捕获通过该进程的stdout和/或stderr进行的操作并将其System.out异步重定向。我希望该过程及其输出重定向在后台运行。到目前为止,我发现这样做的唯一方法是手动产生一个新的线程,该线程将不断读取stdOut并调用适当的write()方法System.out。
stdout
/
stderr
System.out
stdOut
write()
new Thread(new Runnable(){ public void run(){ byte[] buffer = new byte[8192]; int len = -1; while((len = stdOut.read(buffer)) > 0){ System.out.write(buffer, 0, len); } } }).start();
虽然这种方法行得通,但感觉有点脏。最重要的是,它为我提供了另外一个线程来正确管理和终止。有什么更好的方法吗?
在Java 6或更早版本中,唯一的办法是使用所谓的StreamGobbler(开始创建):
StreamGobbler
StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "ERROR"); // any output? StreamGobbler outputGobbler = new StreamGobbler(p.getInputStream(), "OUTPUT"); // start gobblers outputGobbler.start(); errorGobbler.start();
…
private class StreamGobbler extends Thread { InputStream is; String type; private StreamGobbler(InputStream is, String type) { this.is = is; this.type = type; } @Override public void run() { try { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) System.out.println(type + "> " + line); } catch (IOException ioe) { ioe.printStackTrace(); } } }
对于Java 7,请参阅Evgeniy Dorofeev的答案。