2011-08-11 88 views
0

我正在運行以下代碼,並停止在waitfor()函數。可能是什麼原因,我該如何解決?在Java中運行Unix命令

String line; 
Process albumProcess; 
try { 
    albumProcess = Runtime.getRuntime().exec(
    "iconv -f UTF-16 -t UTF-8 /home/gozenem/"+ xmlFileName + 
    ".xml | grep albumID"); 
    albumProcess.waitFor(); 
    BufferedReader in = new BufferedReader(
     new InputStreamReader(albumProcess.getInputStream())); 
    ArrayList<String> lineList = new ArrayList<String>(); 
    while ((line = in.readLine()) != null) { 
    lineList.add(line); 
    } 
    result[0] = lineList.size(); 
    albumProcess.destroy(); 

} catch (Exception e) {} 

回答

2

| grep ...如您所願,因爲getRuntime().exec不明白管道符號不消耗來自命令的輸出。該進程陷入了等待某些東西消耗其輸出它通過僞造命令行參數"|","grep""albumId"

一個shell會明白|execv不會,所以你需要使用bash -c,而不是得到一個殼裏做管道(見java shell for executing/coordinating processes?做管道自己(見Pipe between java processes on command shell not reliable working)。Java 7中有一個新的ProcessBuilder類,使它很容易設置管道,所以你可以使用這些,如果你只是運行在一個流血的邊緣JVM。

一旦你有grep運行,如果有一堆線匹配,它可能仍然填滿了緩衝區,所以你需要一些東西坐在緩衝區上消耗進程的輸出流。移動

albumProcess.waitFor(); 

while循環應該做到這一點。

+0

我如何使用bash -e?我對此很新,如果你能幫助我,那將會很棒。謝謝。 – prgrmmr

+0

@prgrmmr,'bash -c「foo」'啓動一個運行命令'「foo」'的新shell然後退出。 'bash -c「foo | bar」'包括管道。所以,只需引用你的命令,並把'bash -c'放在前面。從manpage:''-c string'如果存在'-c'選項,則從字符串中讀取命令。如果字符串後面有參數,則將它們分配給位置參數,從$ 0開始。 –

+0

過程通常不會等待他們的輸出被消耗,是嗎?它不會只寫入標準輸出流並退出嗎?該過程必須由於其他原因而掛起。 – chesles