標籤:except 返回 等等 line catch builder dog interrupt cal
參考:http://blog.csdn.net/zhu_xun/article/details/19539513
http://www.cnblogs.com/kingcucumber/p/3180146.html
一、Process類
ProcessBuilder.start()建立一個本機進程,並返回一個Process子類的一個執行個體,該執行個體可以擷取進程的相關資訊,也可以控制進程。這個進程沒有自己的終端,它的操作結果io都重新導向到了它的父進程,父進程通過getInputStream(),getOutputStream(),getErrorStream()為子進程提供輸入和擷取輸出,而對於io流如果有緩衝大小限制,則可能出現阻塞,導致死結情況。
可使用destory()方式強制殺掉子進程,exitValue()返回執行結果,如果子進程需要等待返回,調用waitFor()方法將當前線程等待,直到子進程退出。
二、Runtime類
Runtime.getRuntime().exec() 獲得的就是Process類,exec()方法有多個重載可以使用,針對不同的情況設定不同的參數。另外需要注意的是執行的windows和linux的明林的寫法是不同的。
public static void main(String[] args) { String command = "notepad.exe txt.txt"; try { Process process = Runtime.getRuntime().exec(command); BufferedInputStream bis = new BufferedInputStream( process.getInputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(bis)); String line; while ((line = br.readLine()) != null) { System.out.println(line); } process.waitFor(); if (process.exitValue() != 0) { System.out.println("error!"); } bis.close(); br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
三、Apache Common-Exec
強烈建議使用apache的第三方庫,該庫提供了更加詳細的設定和監控方法等等。
執行的命令被稱為CommandLine,可使用該類的addArgument()方法為其添加參數,parse()方法將你提供的命令封裝好一個可執行檔命令。命令是由執行器Executor類來執行的,DefaultExecutor類的execute()方法執行命令,exitValue也可以通過該方法返回接收。設定ExecuteWatchdog可指定進程在出錯後多長時間結束,這樣有效防止了run-away的進程。此外common-exec還支援非同步執行,Executor通過設定一個ExecuteResultHandler類,該類的執行個體會接收住錯誤異常和結束代碼。
CommandLine cmdLine = new CommandLine("AcroRd32.exe");cmdLine.addArgument("/p"); cmdLine.addArgument("/h"); cmdLine.addArgument("${file}"); HashMap map = new HashMap(); map.put("file", new File("invoice.pdf")); commandLine.setSubstitutionMap(map); DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler(); ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000); Executor executor = new DefaultExecutor(); executor.setExitValue(1); executor.setWatchdog(watchdog); executor.execute(cmdLine, resultHandler); // some time later the result handler callback was invoked so we // can safely request the exit value int exitValue = resultHandler.waitFor();
一、Java中關於ProcessBuilder 和 Runtime 類的介紹
在Java中要想執行指令碼或者調用程式必須通過ProcessBuilder 和 Runtime 類,以上兩個類任選一個就行,關於他們的介紹如下:
ProcessBuilder.start() 和 Runtime.exec() 方法都被用來建立一個作業系統進程(執行命令列操作),並返回 Process 子類的一個執行個體,該執行個體可用來控制進程狀態並獲得相關資訊。
Process 類提供了執行從進程輸入、執行輸出到進程、等待進程完成、檢查進程的退出狀態以及銷毀(殺掉)進程的方法。建立進程的方法可能無法針對某些本機平台上的特定進程很好地工作,比如,本機視窗進程,守護進程,Microsoft Windows 上的 Win16/DOS 進程,或者 shell 指令碼。建立的子進程沒有自己的終端或控制台。它的所有標準 io(即 stdin、stdout 和 stderr)操作都將通過三個流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重新導向到父進程。父進程使用這些流來提供到子進程的輸入和獲得從子進程的輸出。因為有些本機平台僅針對標準輸入和輸出資料流提供有限的緩衝區大小,如果讀寫子 進程的輸出資料流或輸入資料流迅速出現失敗,則可能導致子進程阻塞,甚至產生死結。 當沒有 Process 對象的更多引用時,不是刪掉子進程,而是繼續非同步執行子進程。 對於帶有 Process 對象的 Java 進程,沒有必要非同步或並發執行由 Process 對象表示的進程。
每個ProcessBuilder執行個體管理一個進程屬性集。ProcessBuilder的start()方法利用這些屬性建立一個新的Process執行個體。start()方法可以從同一執行個體重複調用,以利用相同或者相關的屬性建立新的子進程。
不同點:
ProcessBuilder.start() 和 Runtime.exec()傳遞的參數有所不同,Runtime.exec()可接受一個單獨的字串,這個字串是通過空格來分隔可執行命令程式和參數的;也可以接受字串數組參數。而ProcessBuilder的建構函式是一個字串列表或者數組。列表中第一個參數是可執行命令程式,其他的是命令列執行是需要的參數。
通過查看JDK源碼可知,Runtime.exec最終是通過調用ProcessBuilder來真正執行操作的。
二、Runtime示範樣本
1.在windows下調用dos命令:
下面示範了在windows下執行dos命令"chdir",並將執行結果輸出的樣本。
public class TestDos { /** * 在windows下執行dos命令並在console端輸出 * * @throws Exception */ public static void main(String[] args) throws Exception { String strCmd = "chdir";//待執行的dos命令(chdir命令作用是列出當前的工作目錄) Process process = Runtime.getRuntime().exec("cmd /k " + strCmd);//通過cmd程式執行cmd命令 //process.waitFor(); //讀取螢幕輸出 BufferedReader strCon = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = strCon.readLine()) != null) { System.out.println(line); } } }
如果不需要進行螢幕輸出的話可以簡寫成如下方式:
public class TestDos { /** * 在windows下調用dos命令 * * @throws Exception */ public static void main(String[] args) throws Exception { String strCmd = "dos命令";//待執行的dos命令 Runtime.getRuntime().exec("cmd /c " + strCmd).waitFor();//通過cmd程式執行dos命令 } }
註:執行dos命令時,需在命令前加上"cmd /x"參數,其中x可以為c或者k值,具體說明如下:
cmd /c chdir 是執行完dir命令後關閉命令視窗。
cmd /k chdir 是執行完dir命令後不關閉命令視窗。
cmd /c start chdir 會開啟一個新視窗後執行dir指令,原視窗會關閉。
cmd /k start chdir 會開啟一個新視窗後執行dir指令,原視窗不會關閉。
2.在windows下調用外部程式:
下面示範了調用QQ程式的過程:
/** * 在windows下調用QQ程式樣本 * */ public class CallQQ { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { Runtime.getRuntime().exec("D:\\Program Files (x86)\\Tencent\\QQ\\QQProtect\\Bin\\QQProtect.exe"); } }
3.在Linux下執行shell命令:
下面示範了在Linux中執行shell命令pwd,並顯示執行結果:
/** * 執行Linux的shell命令並在console端輸出結果 * */ public class CallShell { /** * @throws Exception */ public static void main(String[] args) throws Exception { String strCmd = "pwd";//執行shell命令 Process process = Runtime.getRuntime().exec(strCmd);//通過執行cmd命令調用protoc.exe程式 BufferedReader strCon = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = strCon.readLine()) != null) { System.out.println("java print:"+line); } } }
4.在Linux下調用shell指令碼並輸出結果:
/** * 在linux下調用shell指令碼並在console端輸出指令碼的執行結果 * */ public class CallShell { /** * @throws Exception */ public static void main(String[] args) throws Exception { String strCmd = "/home/zhu/test/test.sh";//待調用shell指令碼 Process process = Runtime.getRuntime().exec(strCmd);//通過執行cmd命令調用protoc.exe程式 BufferedReader strCon = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = strCon.readLine()) != null) { System.out.println("java print:"+line); } } }
三、ProcessBuilder使用樣本
ProcessBuilder的使用參考如下:
String[] as = new String[]{“待執行命令1”,"待執行命令2",.........};
ProcessBuilder pb = new ProcessBuilder(as);
pb.start();
使用ProcessBuilder可以依次執行多個命令
Java調用本地命令