java 調用process


java調用process 有兩種實現方法,一是使用Runtime類,二是使用Process類。

我在最近的項目里用的是Runtime類,接下來寫下總結。

 

有圖有真相(在網上學來一句話)

 
         
 1 package com.lee.demo;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStream;
 6 import java.io.InputStreamReader;
 7 
 8 public class RuntimeDemo01 {
 9 
10     public static void main(String[] args) {
11         String s;
12         StringBuilder sb = new StringBuilder();
13         InputStream fis = null;
14         try {
15             // Process process = Runtime.getRuntime().exec("ping localhost");
Process process = Runtime.getRuntime().exec(new String[]{"sh", "-c", XXXX});
// 注意,我將原來的15行注釋掉了,變成了下面的寫法。聲明,我調用的command是Lunix下的命令,如果你用的是windows的話,不需要這么寫。
// 為什么要使用這樣的寫法,因為項目需要考慮到單引號雙引號等,轉換加/的原因。
16 fis = process.getInputStream(); 17 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fis)); 18 while((s=bufferedReader.readLine()) != null) { 19 sb.append(s);
//sb.append(\n);
20 } 21 System.out.println(sb.toString()); 22 process.waitFor(); 23 System.out.println(process.exitValue()); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } catch (IOException e) { 27 e.printStackTrace(); 28 } finally { 29 try { 30 fis.close(); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 } 35 } 36 }

執行結果如下

使用法: ping [-t] [-a] [-n 要求數] [-l サイズ] [-f] [-i TTL] [-v TOS]            [-r ホップ數] [-s ホップ數] [[-j ホスト一覧] | [-k ホスト一覧]]            [-w タイムアウト] [-R] [-S ソースアドレス] [-4] [-6] ターゲット名オプション:    -t             中斷されるまで、指定されたホストを Ping します。                   統計を表示して続行するには、Ctrl+Break を押してください。                   停止するには、Ctrl+C を押してください。    -a             アドレスをホスト名に解決します。    -n 要求數      送信するエコー要求の數です。    -l サイズ      送信バッファーのサイズです。    -f             パケット內の Don't Fragment フラグを設定します (IPv4 のみ)。    -i TTL         Time To Live です。    -v TOS         Type Of Service (IPv4 のみ。この設定はもう使用されておらず、                   IP ヘッダー內のサービス フィールドの種類に影響しません)。    -r ホップ數    指定したホップ數のルートを記録します (IPv4 のみ)。    -s ホップ數    指定したホップ數のタイムスタンプを表示します (IPv4 のみ)。    -j ホスト一覧  一覧で指定された緩やかなソース ルートを使用します                   (IPv4 のみ)。    -k ホスト一覧  一覧で指定された厳密なソース ルートを使用します                   (IPv4 のみ)。    -w タイムアウト                   応答を待つタイムアウトの時間 (ミリ秒) です。    -R             ルーティング ヘッダーを使用して逆ルートもテストします                   (IPv6 のみ)。    -S ソースアドレス                   使用するソース アドレスです。    -4             IPv4 の使用を強制します。    -6             IPv6 の使用を強制します。

如果你執行的命令是 ping localhost的話,那么是可以正常執行並返回黑屏下一樣的結果的。

在這里說一下我遇到的幾個坑。

首先,lunix下執行和windows下執行不一樣。比如上面的例子中,ping這個命令,沒有添加參數時,在執行結果中會打出黑屏下一樣的提示信息,但是lunix下不行,在程序中需要process.getErrorStream(),這樣才能得到一致的結果。

第二個坑,是要記得添加process.waitFor();這行代碼,代碼的意思是 線程一直到process結束再往下執行。如果不寫這行代碼,那么process執行的同時,線程在往下執行,到后面23行的代碼會拋出error。此外,process.waitFor()代碼要放在,對輸入流的操作之后,因為每次輸入流讀取的大小是有限制的,如果超過最大值,而輸入流中的內容沒有被讀取,那么久會發生阻塞,到時程序一直停在那里。

第三個坑,在上文中代碼的第17行里,使用了匿名類的new InputStreamReader,在性能測試的時候,報錯,can not open too many files,原因是InputStreamReader使用了之后,最后沒有將他close。一定要在finally中將它close掉。

第四個坑,代碼第18行,readLine()方法,大家很熟悉。我們看一下API中的定義。

public String readLine()
                throws IOException

Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.

Returns:
    A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
Throws:
    IOException - If an I/O error occurs

 在returns中,明確寫明,只返回內容,不會返回換行符號等。這就導致最后我們取得的內容是一行String,很長。我決定在19行后,加個換行符,這樣就可以換行了。

 

接下來,簡單說明一下Process類,要說的是,自jdk1.5起,官方建議,使用ProcessBuilder.start()來啟動process

官方文檔地址: https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html

其實JDK中Runtime最終調用的是processbuilder。

processbuilder提供的功能更加豐富,可以設置工作目錄,環境變量等。

推薦一篇文章,processBuilder介紹得很好。

http://www.cnblogs.com/taven/archive/2011/12/17/2291460.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM