2012-01-05 114 views
9

是否可以將由ProcessBuilder創建的一個進程的輸出傳遞給由另一個ProcessBuilder創建的另一個進程?例如,如果我試圖執行此shell命令:將ProcessBuilder的輸出管道輸出到另一個ProcessBuilder

ls | grep build.xml 

我應該如何使用ProcessBuilder執行此操作?

爲@erdinc建議,我嘗試這樣做:

Process process = Runtime.getRuntime().exec("ls"); 
InputStream is = process.getInputStream(); 
byte[] buf = new byte[1000]; 
is.read(buf); 
String parameter = new String(buf); 
System.out.println("grep build " + parameter); 

Process proc2 = Runtime.getRuntime().exec("grep build " + parameter); 
InputStream is2 = proc2.getInputStream(); 
byte[] buf2 = new byte[1000]; 
is2.read(buf2); 
String result = new String(buf2); 
System.out.println("proc2 result: " + result); 

,但它會產生不同的結果進行比較時,我直接在shell中運行的腳本。我在哪裏做錯了?

解決:請參考菲利普·溫德勒溶液

回答

6

解決方案的問題是它只讀取ls輸出中的前1000個字節並將它們傳遞給grep。由於您不知道ls之前的輸出量,因此您需要反覆讀取它直到耗盡。

下面是使用BufferedReader類的解決方案,這將輸出的每一行發送到grep:

Process lsProcess = Runtime.getRuntime().exec("ls"); 
BufferedReader lsOutput = new BufferedReader(new InputStreamReader(lsProcess.getInputStream())); 
Process grepProcess = Runtime.getRuntime().exec("grep build.xml"); 
BufferedWriter grepInput = new BufferedWriter(new OutputStreamWriter(grepProcess.getOutputStream())); 

String line; 
// read each line from ls until there are no more 
while ((line = lsOutput.readLine()) != null) { 
    // and send them to grep 
    grepInput.write(line); 
    grepInput.newLine(); 
} 

// send end-of-file signal to grep so it will terminate itself 
grepInput.close(); 

當然,你需要添加相應的錯誤處理在這裏。 如果此解決方案太慢,可以省略讀取器和寫入器,並將byte[]數組直接從輸入流傳遞到輸出流。

但是,更好的解決方案不是使用ls和grep在文件系統中查找文件,而是使用適當的Java API。例如,如果爲您感興趣的目錄創建一個File對象,則可以使用其上的各種listFiles方法列出此目錄中的所有文件。這種方法非常簡單,便於攜帶,不易出錯並且可能更快。

+0

您的解決方案可行!謝謝菲利普:我實際上會使用這個代碼來調用幾個外部應用程序,如chasen和moses(機器翻譯工具)。 ls | grep的例子只是爲了簡化問題,但感謝您的建議:D我會標記問題解決並upvote您的解決方案。 – ndriks 2012-01-08 12:00:58

0

可以使用getInputStream方法比通過作爲參數第二處理。 示例代碼;

 process = Runtime.getRuntime().exec("ls"); 
     InputStream is = process.getInputStream(); 
     byte[] buf = new byte[1000]; 
     is.read(buf); 
     String parameter = new String(buf); 
     System.out.println(parameter); 
     Runtime.getRuntime().exec("grep build.xml " + parameter); 
+0

但如何將「ls」輸入流傳遞給「grep」進程?我似乎無法在Process中找到方法setInputStream。也可以用ProcessBuilder完成嗎? – ndriks 2012-01-05 22:29:04

+0

我試過你的解決方案@erdinc,但它產生了不同的結果,而不是直接在shell中運行命令。我編輯了這個問題來展示我所做的。 僅供參考,我沒有試圖用ls結果作爲參數運行grep,但我試圖將ls的結果傳遞給grep進程。 – ndriks 2012-01-08 09:02:28