1. 程式人生 > >Runtime.getRuntime().exec()需要註意的地方

Runtime.getRuntime().exec()需要註意的地方

window dsta 進程 明顯 trac get win 方法 mes

文章出處http://www.cnblogs.com/fclbky/p/6112180.html

有時候我們可能需要調用系統外部的某個程序,此時就可以用Runtime.getRuntime().exec()來調用,他會生成一個新的進程去運行調用的程序。

此方法返回一個java.lang.Process對象,該對象可以得到之前開啟的進程的運行結果,還可以操作進程的輸入輸出流。

Process對象有以下幾個方法:

  1、destroy()      殺死這個子進程

  2、exitValue()      得到進程運行結束後的返回狀態

  3、waitFor()       得到進程運行結束後的返回狀態,如果進程未運行完畢則等待知道執行完畢

  4、getInputStream()  得到進程的標準輸出信息流

  5、getErrorStream()  得到進程的錯誤輸出信息流

  6、getOutputStream() 得到進程的輸入流

現在來講講exitValue(),當線程沒有執行完畢時調用此方法會跑出IllegalThreadStateException異常,最直接的解決方法就是用waitFor()方法代替。

但是waitFor()方法也有很明顯的弊端,因為java程序給進程的輸出流分配的緩沖區是很小的,有時候當進程輸出信息很大的時候回導致緩沖區被填滿,如果不及時處理程序會阻塞。如果程序沒有對進程的輸出流處理的會就會導致執行exec()的線程永遠阻塞,進程也不會執行下去直到輸出流被處理或者java程序結束。

解決的方法就是處理緩沖區中的信息,開兩個線程分別去處理標準輸出流和錯誤輸出流。

程序如下:

技術分享 技術分享
public class ExecTest {
    
    public static void main(String[] args) throws IOException, InterruptedException {
      String cmd = "cmd /c dir c:\\windows";
      final Process process = Runtime.getRuntime().exec(cmd);
      printMessage(process.getInputStream());
      printMessage(process.getErrorStream());
      int value = process.waitFor();
      System.out.println(value);
    }
    
    private static void printMessage(final InputStream input) {
      new Thread(new Runnable() {
         public void run() {
            Reader reader = new InputStreamReader(input);
            BufferedReader bf = new BufferedReader(reader);
            String line = null;
             try {
                while((line=bf.readLine())!=null) {
                    System.out.println(line);
                }
             } catch (IOException e) {
                e.printStackTrace();
             }
         }
      }).start();
    }
}
技術分享 技術分享

如上程序,讀取進程的輸出信息並打印到控制臺就不會發生阻塞,程序能正常的結束。

tips:

  cmd命令不能需要加上cmd /c才能執行,不然java會去path中找dir.exe

  在windows一般字符集編碼為GBK,需要在轉換成Reader的時候指定為GBK編碼.

Runtime.getRuntime().exec()需要註意的地方