激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - Java魔法堂之調用外部程序的方法

Java魔法堂之調用外部程序的方法

2021-08-08 11:42^_^肥仔John Java教程

這篇文章主要介紹了Java魔法堂:調用外部程序的相關知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧

前言

Java雖然五臟俱全但總有軟肋,譬如獲取CPU等硬件信息,當然我們可以通過JNI調用C/C++來獲取,但對于對C/C++和Windows API不熟的碼農是一系列復雜的學習和踩坑過程。那能不能通過簡單一些、學習成本低一些的方式呢?答案是肯定的,在功能實現放在首位的情況下,借他山之石是最簡潔有力的做法。

認識java.lang.Runtime#exec方法

作用:用于調用外部程序,并重定向外部程序的標準輸入、標準輸出和標準錯誤到緩沖池。功能就是和windows的“運行”一樣。

Java魔法堂之調用外部程序的方法

重載方法說明

?
1
2
3
4
5
6
Runtime#exec(String command);
Runtime#exec(String command, String[] envp);
Runtime#exec(String command, String[] envp, File workdir);
Runtime#exec(String[] cmdArray);
Runtime#exec(String[] cmdArray, String[] envp);
Runtime#exec(String[] cmdArray, String[] envp, File workdir);

String[] envp 作為調用命令前設置的會話級環境變量。
1.1. 變量作用域:命令運行結束后,通過該參數設置的環境變量將失效;
1.2. 設置方式:variableName=variableValue,如Process proc = r.exec("cmd /c dir > %dest%", new String[]{"dest=c:\\dir.txt"});File workdir 用于設置當前工作目錄,譬如我們需要執行位于D:\tools下的echo.exe程序,那么可以這樣調用Process proc = r.exec("echo.exec", null, new File("D:\\tools"));String command 即為需要調用的外部程序,以及命令行參數等。Windows下調用系統命令,像dir等命令是由cmd解析器解釋執行的,因此若直接寫"dir"則會被認為在當前工作目錄下有一個"dir.exe"文件,那么當然會執行失敗;在Linux下調用ls等是同樣道理,因此請按如下方式調用cmd和shell命令:
3.1. 調用CMD命令的方式為Process proc = r.exec(String.format("cmd /c %s", "cmd命令,如dir、type等")),若要啟動一個新的Console執行命令,只需要將dir改寫為start dir即可;
3.2. 調用Shell命令的方式為Process proc = r.exec(String.format("/bin/sh -c %s", "shell命令,如ls、cat等")),若要啟動一個新的Terminal執行命令,只需要將ls改寫為xterm -e ls即可;String[] cmdArray 功能和String command一樣,但命令行的每個部分將作被獨立分隔出來作為數組中的元素。如cmd /c dir必須分割為new String[]{"cmd", "/c", "dir"},而不能分割為new String[]{"cmd /c", "dir"}

輸入重定向

廢話少說,直接看代碼!

?
1
2
3
4
5
6
7
8
9
10
try {                                                     
 String cmd = "cmd /c start cmd.exe";                                   
 Process child = Runtime.getRuntime().exec(cmd);                              
 OutputStream output = child.getOutputStream();                              
 output.write("cd C:/ /r/n".getBytes());                                  
 output.flush();                                              
 output.write("dir /r/n".getBytes());                                   
 output.close();                                              
}                                                       
catch (IOException e) {}

輸出重定向

注意:不支持直接使用>或>>執行標準輸出重定向。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
String cmd = "/path/to/getipconfig.bat"; // 自己寫的bat腳本文件,里面包含ipconfig /all命令。
Process p;                                                  
                                                           
try {                                                     
 p = Runtime.getRunTime().exec(cmd);                                    
 InputStream input = p.getInputStream();                                  
 InputStreamReader streamReader = new InputStreamReader(input);                      
 BufferedReader bufReader = new BufferedReader(streamReader);                       
 String line = null;                                            
                                                           
 while ((line = bufReader.readLine()) != null) {                              
  System.out.println(line);                                         
 }                                                     
}                                                       
catch (IOException e) {}

為什么不能使用>>>實現輸出重定向呢?

通過Process實例.getInputStream()Process實例.getErrorStream()獲取的輸入流和錯誤信息流是緩沖池是當前Java程序提供的,而不是直接獲取外部程序的標準輸出流和標準錯誤流。
即通過Runtime#exec調用外部程序時,外部程序的標準輸出流和標準錯誤流已經被Java程序接管。那么在命令中企圖通過>>>實現輸出重定向顯然已無效果。

Java魔法堂之調用外部程序的方法

另外,緩沖池的容量是一定的,因此若外部程序在運行過程中不斷向緩沖池輸出內容,當緩沖池填滿,那么外部程序將暫停運行直到緩沖池有空位可接收外部程序的輸出內容為止。(采用xcopy命令復制大量文件時將會出現該問題)
解決辦法就是當前的Java程序不斷讀取緩沖池的內容,從而為騰出緩沖池的空間。如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Runtime r = Runtime.getRuntime();
try{
 Process proc = r.exec("cmd /c dir"); // 假設該操作為造成大量內容輸出
 // 采用字符流讀取緩沖池內容,騰出空間
 BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream(), "gbk")));
 String line = null;
 while ((line = reader.readLine()) != null){
   System.out.println(line);
 }
 
 // 或采用字節流讀取緩沖池內容,騰出空間
 // ByteArrayOutputStream pool = new ByteArrayOutputStream();
 // byte[] buffer = new byte[1024];
 // int count = -1;
 // while ((count = proc.getInputStream().read(buffer)) != -1){
 //  pool.write(buffer, 0, count);
 //  buffer = new byte[1024];
 // }
 // System.out.println(pool.toString("gbk"));
 
 int exitVal = proc.waitFor();
 System.out.println(exitVal == 0 ? "成功" : "失敗");
}
catch(Exception e){
 e.printStackTrace();
}

注意:外部程序在執行結束后將會自動關閉,否則不管是字符流還是字節流均由于既讀不到數據,又讀不到流結束符而出現阻塞Java進程運行的情況。

簡化輸入輸出重定向的java.lang.ProcessBuilder

功能和java.lang.runtime#exec一樣,只是java.lang.ProcessBuilder僅接收命令行以數組形式傳遞給java.lang.ProcessBuilder#command()而已。

基本使用

?
1
2
3
4
5
6
7
8
9
ProcessBuilder pb = new ProcessBuilder();                                                                
// pb.command("cmd /c dir"); 這樣會報錯                                                                 
// 或者寫到new ProcessBuilder("cmd", "/c", "dir")                                                            
pb.command("cmd", "/c", "dir");                                                                     
try {                                                                                  
 Process process = pb.start();                                                                    
 // 后面都是操作Process實例的方法                                                                   
}                                                                                    
catch (IOException e){}

重定向

?
1
2
3
public ProcessBuilder redirectInput(File file) // 輸入重定向                                                      
public ProcessBuilder redirectOutput(File file) // 輸出重定向                                                      
public ProcessBuilder redirectError(File file) // 異常重定向

示例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
try {                                                                                 
 ProcessBuilder pb = new ProcessBuilder("cmd");                                                           
 // 在標準輸入中,通過換行符分隔多行命令。                                                             
 // commands.txt的內容為                                                                      
 // javac Demo.java                                                                         
 // java Demo                                                                            
 File commands = new File("/path/to/commands.txt");                                                         
 File error = new File("/path/to/error");                                                              
 File output = new File("/path/to/output");                                                             
                                                                                         
 pd.redirectInput(commands);                                                                    
 pd.redirectOutput(output);                                                                     
 pd.redirectError(error);                                                                      
                                                                                         
 pd.start();                                                                            
}                                                                                   
catch(Exception e) {                                                                          
 e.printStackTrace();                                                                        
}

java.lang.ProcessAPI說明

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 以非阻塞方式獲取子進程執行的返回值(習慣0表示正常結束)。若子進程尚未完成時調用該方法,則會報異常`java.lang.IllegalThreadStateException`
int exitValue()     
// 以阻塞方式獲取子進程執行的返回值。若進程尚未完成則會等待子進程完成后才恢復當前線程。
// 問題:若子進程無法正常關閉,則會導致Java線程一直掛起;
// 返回值為子進程的退出碼
int waitFor()。                                 
// 如果超時前子進程結束,那么返回`true` ,否則返回`false`
boolean waitFor(long timeout, TimeUnit unit)
// 強行終止子進程,但調用后子進程不會馬上被終止,所以立即調`boolean isAlive()`方法可能會返回`true`,因此需配合`waitFor`使用。
void destory()
// 默認實現為調用`void destory()`方法。從JDK1.8開始提供。
Process destoryForcibly()
// 如果子進程還沒結束則返回`true` 。從JDK1.8開始提供。                                         
boolean isAlive()
// 獲取子進程的異常輸出流,如果子進程以`ProcessBuilder`創建,且通過`ProcessBuilder.redirectError`設置重定向,那么該方法返回`null`                         
InputStream getErrorStream()
// 獲取子進程的標準輸出流,如果子進程以`ProcessBuilder`創建,且通過`ProcessBuilder.redirectOutput`設置重定向,那么該方法返回`null`
InputStream getInputStream()
// 獲取子進程的標準輸入流,如果子進程以`ProcessBuilder`創建,且通過`ProcessBuilder.redirectInput`設置重定向,那么該方法返回`null`
OutputStream getOutputStream()

總結

到此這篇關于Java魔法堂:調用外部程序的文章就介紹到這了,更多相關Java調用外部程序內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/fsjohnhuang/p/14396218.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人精品一区二区三区中文字幕 | av在线一区二区三区四区 | 羞羞视频免费网站含羞草 | 成人资源在线 | 在线成人免费观看 | 欧美日韩精品不卡一区二区三区 | 成人福利网| 日韩午夜一区二区三区 | 欧美日韩在线视频一区 | 午夜精品视频免费观看 | 国产一级在线看 | 免费在线观看午夜视频 | hd porn 4k video xhicial| 久久久一区二区三区精品 | 九九热这里只有精品8 | 黄色片免费在线播放 | 欧美日韩亚洲精品一区二区三区 | 日本aaaa片毛片免费观看视频 | a黄网站| h视频免费看 | av电影免费看 | 午夜在线小视频 | 永久av在线免费观看 | 一区二区三区欧美在线 | 日本在线观看一区二区 | 男女无套免费视频 | 极品美女一级毛片 | 免费在线性爱视频 | 欧美成人午夜一区二区三区 | 热re91久久精品国产99热 | 一区二区三区手机在线观看 | 日本aaaa片毛片免费观看视频 | 欧美一级毛片欧美一级成人毛片 | 依依成人综合 | 草莓福利社区在线 | 激情久久婷婷 | 51色视频| 欧美成人午夜 | 性欧美视频在线观看 | 欧美一级电影在线观看 | 欧美1区2区在线观看 |