ProcessBuilder:轉(zhuǎn)發(fā)stdout和stderr啟動進(jìn)程而不阻塞主線程我正在使用ProcessBuilder在Java中構(gòu)建一個(gè)進(jìn)程,如下所示:ProcessBuilder pb = new ProcessBuilder()
.command("somecommand", "arg1", "arg2")
.redirectErrorStream(true);Process p = pb.start();InputStream stdOut = p.getInputStream();現(xiàn)在我的問題如下:我想捕獲通過該進(jìn)程的stdout和/或stderr的任何內(nèi)容,并將其重定向到System.out異步。我希望進(jìn)程及其輸出重定向在后臺運(yùn)行。到目前為止,我發(fā)現(xiàn)這樣做的唯一方法是手動生成一個(gè)新的線程,該線程將連續(xù)讀取stdOut,然后調(diào)用適當(dāng)?shù)膚rite()方法System.out。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();雖然這種方法很有效,但感覺有點(diǎn)臟。最重要的是,它為我提供了一個(gè)正確管理和終止的線程。有沒有更好的方法來做到這一點(diǎn)?
3 回答

慕的地6264312
TA貢獻(xiàn)1817條經(jīng)驗(yàn) 獲得超6個(gè)贊
使用ProcessBuilder.inheritIO
它,它將子進(jìn)程標(biāo)準(zhǔn)I / O的源和目標(biāo)設(shè)置為與當(dāng)前Java進(jìn)程的源和目標(biāo)相同。
Process p = new ProcessBuilder().inheritIO().command("command1").start();
如果Java 7不是一個(gè)選項(xiàng)
public static void main(String[] args) throws Exception { Process p = Runtime.getRuntime().exec("cmd /c dir"); inheritIO(p.getInputStream(), System.out); inheritIO(p.getErrorStream(), System.err);}private static void inheritIO(final InputStream src, final PrintStream dest) { new Thread(new Runnable() { public void run() { Scanner sc = new Scanner(src); while (sc.hasNextLine()) { dest.println(sc.nextLine()); } } }).start();}
子進(jìn)程完成后線程將自動死亡,因?yàn)?code>srcEOF 會自動死亡。

HUX布斯
TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超6個(gè)贊
一個(gè)靈活的Java 8 lambda解決方案,允許您提供一個(gè)Consumer
逐行處理輸出(例如,記錄它)的解決方案。run()
是一個(gè)沒有檢查異常拋出的單線程。作為實(shí)施的替代Runnable
,它可以Thread
像其他答案所暗示的那樣延伸。
class StreamGobbler implements Runnable { private InputStream inputStream; private Consumer<String> consumeInputLine; public StreamGobbler(InputStream inputStream, Consumer<String> consumeInputLine) { this.inputStream = inputStream; this.consumeInputLine = consumeInputLine; } public void run() { new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumeInputLine); }}
然后你可以使用它,例如:
public void runProcessWithGobblers() throws IOException, InterruptedException { Process p = new ProcessBuilder("...").start(); Logger logger = LoggerFactory.getLogger(getClass()); StreamGobbler outputGobbler = new StreamGobbler(p.getInputStream(), System.out::println); StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), logger::error); new Thread(outputGobbler).start(); new Thread(errorGobbler).start(); p.waitFor();}
這里輸出流被重定向到,System.out
并且錯(cuò)誤級別由錯(cuò)誤級別記錄logger
。
添加回答
舉報(bào)
0/150
提交
取消