?
大家都知道java調用cmd 用的是Runtime的exec()方法。該方法最終重啟一個進程去執行命令,因為該方法最終調用了
ProcessBuilder:
1
?public?Process?exec(String[]?strings,?String[]?strings_2_,?File?file)
2
????throws?IOException?
{
3
????return?new?ProcessBuilder(strings).environment(strings_2_).directory
4
???????????(file).start();
5
????} 既然是重啟了一個進程,那么就存在異步的問題,但是在很多情況在更想同步的調用Runtime的exec(),那么怎么辦呢?
Runtime.exec()的返回值Process提供了waitFor()方法,可以達到阻塞新進程的目的。但是只調用waitFor(),該字線程就會
一直阻塞,所以只調用waitFor()還是不夠的,我們需要以讀取他的輸出流的方式來阻塞住線程,當輸出流讀取結束的
時候讓阻塞結束,代碼如下:


BufferedReader?bufferedReader?=?new?BufferedReader(new?InputStreamReader(process.getInputStream()));
????????String?str?=?"";
????????

????????while?((str?=?bufferedReader.readLine())?!=?null)?
{
????????????System.out.println(str);
????????}
????process.waitFor();? ?? 通過讀取輸出流和調用process.waitFor()可以的實現調用Runtime.exec()的同步。
?? 另外還有一種情況可以使Runtime.exec()出現阻塞,Runtime的exec()在執行時會產生兩種輸出流:錯誤輸出流和標準輸出流,當進程結束時會關閉這兩個流,在上面的代碼里只讀取了標準輸出流而沒有導致錯誤輸出流,由于錯誤輸出流中的數據沒有被讀取,進程就不會結束,因此調用readLine()方法時整個程序就會阻塞,因此,我們不僅要讀取標準輸出流還要讀取錯誤輸出流,由于讀取這些流都會阻塞,所以想同時讀取兩個流還不是那么容易,一種辦法就是啟動線程分別讀取不同的輸出流,另外一個辦法就是使用ProcessBuilder來執行(前面已經說過了Runtime.exec()最終也是調用ProcessBuilder來執行的),因為ProcessBuilder有一個redirectErrorStream(),將方法設置為redirectErrorStream(true),就可以使錯誤輸出流合并到標準輸出流,這樣我們就只需要讀取標準輸出流就可以完全解決問題了,代碼如下:


?1
private?static?void?execCmd(Properties?properties)?throws?Exception?
{
?2
?3
?4
????????File?file?=?new?File("執行命令的目錄");
?5
?6
????????ListString>?cmdList?=?new?ArrayListString>();
?7
????????cmdList.add("cmd.exe");
?8
????????cmdList.add("/c");
?9
????????cmdList.add(CMD);//CMD是執行的命令
10
????????
11
????????ProcessBuilder?pb?=?new?ProcessBuilder(cmdList);
12
????????pb.directory(file);
13
????????pb.redirectErrorStream(true);//將錯誤輸出流合并到標準輸出流
14
????????Process?process?=?pb.start();
15
????????
16
????????print(process);
17
????}
18
19
????
20
????public?static?void?print(Process?process)?throws?Exception?
{
21
????????BufferedReader?bufferedReader?=?new?BufferedReader(new?InputStreamReader(process.getInputStream()));
22
????????String?str?=?"";
23
????????????
24
????????while?((str?=?bufferedReader.readLine())?!=?null)?
{
25
????????????System.out.println(str);
26
????????}
27
????????
28
????????cs.close();
29
????????process.waitFor();?
30
????} 還是也介紹下使用線程來分別讀取錯誤輸出流和標準輸出流吧:


?1
import?java.util.*;
?2
import?java.io.*;
?3
?4
class?StreamWatch?extends?Thread?
{
?5
InputStream?is;
?6
?7
String?type;
?8
?9
ListString>?output?=?new?ArrayListString>();
10
11
boolean?debug?=?false;
12
13
StreamWatch(InputStream?is,?String?type)?
{
14
???this(is,?type,?false);
15
}
16
17
StreamWatch(InputStream?is,?String?type,?boolean?debug)?
{
18
???this.is?=?is;
19
???this.type?=?type;
20
???this.debug?=?debug;
21
}
22
23
public?void?run()?
{
24
???try?
{
25
????PrintWriter?pw?=?null;
26
27
????InputStreamReader?isr?=?new?InputStreamReader(is);
28
????BufferedReader?br?=?new?BufferedReader(isr);
29
????String?line?=?null;
30
????while?((line?=?br.readLine())?!=?null)?
{
31
?????output.add(line);
32
?????if?(debug)
33
??????System.out.println(type?+?">"?+?line);
34
????}
35
????if?(pw?!=?null)
36
?????pw.flush();
37
???}?catch?(IOException?ioe)?
{
38
????ioe.printStackTrace();
39
???}
40
}
41
42
public?ListString>?getOutput()?
{
43
???return?output;
44
}
45
}
46
47
public?class?Test5?
{
48
public?static?void?main(String?args[])?
{
49
???try?
{
50
????ListString>?list?=?new?ArrayListString>();
51
????ProcessBuilder?pb?=?null;
52
????Process?p?=?null;
53
54
????//?list?the?files?and?directorys?under?C:\
55
????list.add("CMD.EXE");
56
????list.add("/C");
57
????list.add("dir1");
58
????pb?=?new?ProcessBuilder(list);
59
????pb.directory(new?File("C:\\"));
60
????p?=?pb.start();
61
62
????//?process?error?and?output?message
63
????StreamWatch?errorWatch?=?new?StreamWatch(p.getErrorStream(),
64
??????"ERROR");
65
????StreamWatch?outputWatch?=?new?StreamWatch(p.getInputStream(),
66
??????"OUTPUT");
67
68
????//?start?to?watch
69
????errorWatch.start();
70
????outputWatch.start();
71
72
????//wait?for?exit
73
????int?exitVal?=?p.waitFor();
74
75
????//print?the?content?from?ERROR?and?OUTPUT
76
????System.out.println("ERROR:?"?+?errorWatch.getOutput());
77
????System.out.println("OUTPUT:?"?+?outputWatch.getOutput());
78
???
79
????System.out.println("the?return?code?is?"?+?exitVal);
80
81
???}?catch?(Throwable?t)?
{
82
????t.printStackTrace();
83
???}
84
}
85
}
86
87
88
?
好了,今天就先寫到這里吧。