2012-01-05 15 views
1

我知道處理Java中外部過程的輸出/錯誤流的規範方式是使用兩個額外線程來將數據從輸出和錯誤流可能會阻止進程。在沒有額外線程的情況下在Java中分別處理輸出/錯誤的過程

現在關於以下內容?

public static void main(String[] args) throws IOException, InterruptedException { 
    ProcessBuilder processBuilder = new ProcessBuilder(args); 
    Process process = processBuilder.start(); 

    InputStream outputStream = null, errorStream = null; 
    ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(); 
    ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream(); 
    try { 
    outputStream = process.getInputStream(); 
    errorStream = process.getErrorStream(); 

    byte[] tmp = new byte[1024]; 

    while (true) { 
     int outputBytes = readAvailablOnce(outputStream, outputBuffer, tmp); 
     int errorBytes = readAvailablOnce(errorStream, errorBuffer, tmp); 
     if (outputBytes == 0 && errorBytes == 0) { 
     try { 
      process.exitValue(); 
      break; 
     } catch (IllegalThreadStateException e) { 
      // keep on looping 
     } 
     } 
    } 
    readAvailableAll(outputStream, outputBuffer, tmp); 
    readAvailableAll(errorStream, errorBuffer, tmp); 

    } finally { 
    closeQuietly(outputStream); 
    closeQuietly(errorStream); 
    } 

    System.out.println(outputBuffer.toString("ASCII")); 
    System.err.println(errorBuffer.toString("ASCII")); 
    System.err.println("exit code: " + process.exitValue()); 
} 

private static void closeQuietly(InputStream in) { 
    if (in != null) { 
    try { 
     in.close(); 
    } catch (IOException e) { 
     // ignored 
    } 
    } 
} 

private static int readAvailablOnce(
    InputStream inputStream, OutputStream outputStream, byte[] buffer) 
throws IOException { 
    int bytesRead = 0; 
    if (inputStream.available() > 0) { 
    bytesRead = inputStream.read(buffer); 
    outputStream.write(buffer, 0, bytesRead); 
    } 
    return bytesRead; 
} 

private static void readAvailableAll(
    InputStream inputStream, OutputStream outputStream, byte[] buffer) 
throws IOException { 
    if (inputStream.available() > 0) { 
    int bytesRead = 0; 
    while ((bytesRead = inputStream.read(buffer)) >= 0) { 
     outputStream.write(buffer, 0, bytesRead); 
    } 
    } 
} 

在我試過的幾個例子(運行「dir」,「ps aux」等)中,這實際運行良好。除非你開始用Buffers和CharsetDecoders做一些或多或少複雜的事情,它也有不允許你逐行處理輸出(這裏你在做任何事情之前緩衝所有東西)的缺點。

不過,它對於沒有無法接受的大輸出的任何東西都很有用(儘管在使用它之前沒有任何東西強迫我們緩衝整個輸出)。

我只嘗試過1.5和1.6的JVM(Windows XP和Linux)。另外,這段代碼假定進程的最終輸出位將隨時可用於讀取(InputStream.available()> 0)。

任何人都會知道這個代碼有什麼錯誤(或者是否有更好的想法)?

+0

你知道[codereview](http://codereview.stackexchange.com/)嗎?它處於測試階段,但它似乎工作得很好。 – 2012-01-06 03:30:42

+0

我沒有!謝謝。我感興趣的是通用解決方案是否實際上在Java中工作(超出我的小測試),因爲兩種額外線程方法是經典答案,並且它不正確。不過,如果在兩種工具中都沒有不禮貌的做法,我可能會在「codereview」中提交。 – viphe 2012-01-06 07:08:35

回答

1

我會用ProcessBuilder.redirectErrorStream(true)它允許你讀取當前線程中的一個流。你不需要任何後臺線程。

+0

如果你不關心合併標準和錯誤輸出,你提出的是確定的方式。修改我的描述... – viphe 2012-01-06 08:29:02

相關問題