亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java魔法堂之調(diào)用外部程序的方法

 更新時(shí)間:2021年02月11日 07:27:41   作者:^_^肥仔John  
這篇文章主要介紹了Java魔法堂:調(diào)用外部程序的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

前言

Java雖然五臟俱全但總有軟肋,譬如獲取CPU等硬件信息,當(dāng)然我們可以通過(guò)JNI調(diào)用C/C++來(lái)獲取,但對(duì)于對(duì)C/C++和Windows API不熟的碼農(nóng)是一系列復(fù)雜的學(xué)習(xí)和踩坑過(guò)程。那能不能通過(guò)簡(jiǎn)單一些、學(xué)習(xí)成本低一些的方式呢?答案是肯定的,在功能實(shí)現(xiàn)放在首位的情況下,借他山之石是最簡(jiǎn)潔有力的做法。

認(rèn)識(shí)java.lang.Runtime#exec方法

作用:用于調(diào)用外部程序,并重定向外部程序的標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤到緩沖池。功能就是和windows的“運(yùn)行”一樣。

重載方法說(shuō)明

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

輸入重定向

廢話少說(shuō),直接看代碼!

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) {}  

輸出重定向

注意:不支持直接使用>或>>執(zhí)行標(biāo)準(zhǔn)輸出重定向。

String cmd = "/path/to/getipconfig.bat"; // 自己寫(xiě)的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) {}     

為什么不能使用>>>實(shí)現(xiàn)輸出重定向呢?

通過(guò)Process實(shí)例.getInputStream()Process實(shí)例.getErrorStream()獲取的輸入流和錯(cuò)誤信息流是緩沖池是當(dāng)前Java程序提供的,而不是直接獲取外部程序的標(biāo)準(zhǔn)輸出流和標(biāo)準(zhǔn)錯(cuò)誤流。
即通過(guò)Runtime#exec調(diào)用外部程序時(shí),外部程序的標(biāo)準(zhǔn)輸出流和標(biāo)準(zhǔn)錯(cuò)誤流已經(jīng)被Java程序接管。那么在命令中企圖通過(guò)>>>實(shí)現(xiàn)輸出重定向顯然已無(wú)效果。

另外,緩沖池的容量是一定的,因此若外部程序在運(yùn)行過(guò)程中不斷向緩沖池輸出內(nèi)容,當(dāng)緩沖池填滿,那么外部程序?qū)和_\(yùn)行直到緩沖池有空位可接收外部程序的輸出內(nèi)容為止。(采用xcopy命令復(fù)制大量文件時(shí)將會(huì)出現(xiàn)該問(wèn)題)
解決辦法就是當(dāng)前的Java程序不斷讀取緩沖池的內(nèi)容,從而為騰出緩沖池的空間。如:

Runtime r = Runtime.getRuntime();
try{
 Process proc = r.exec("cmd /c dir"); // 假設(shè)該操作為造成大量?jī)?nèi)容輸出
 // 采用字符流讀取緩沖池內(nèi)容,騰出空間
 BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream(), "gbk")));
 String line = null;
 while ((line = reader.readLine()) != null){
   System.out.println(line);
 }

 // 或采用字節(jié)流讀取緩沖池內(nèi)容,騰出空間
 // 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();
}

注意:外部程序在執(zhí)行結(jié)束后將會(huì)自動(dòng)關(guān)閉,否則不管是字符流還是字節(jié)流均由于既讀不到數(shù)據(jù),又讀不到流結(jié)束符而出現(xiàn)阻塞Java進(jìn)程運(yùn)行的情況。

簡(jiǎn)化輸入輸出重定向的java.lang.ProcessBuilder

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

基本使用

ProcessBuilder pb = new ProcessBuilder();                                                                 
// pb.command("cmd /c dir"); 這樣會(huì)報(bào)錯(cuò)                                                                  
// 或者寫(xiě)到new ProcessBuilder("cmd", "/c", "dir")                                                             
pb.command("cmd", "/c", "dir");                                                                      
try {                                                                                   
 Process process = pb.start();                                                                     
 // 后面都是操作Process實(shí)例的方法                                                                    
}                                                                                     
catch (IOException e){}   

重定向

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

示例

try {                                                                                  
 ProcessBuilder pb = new ProcessBuilder("cmd");                                                            
 // 在標(biāo)準(zhǔn)輸入中,通過(guò)換行符分隔多行命令。                                                              
 // commands.txt的內(nèi)容為                                                                       
 // 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說(shuō)明

// 以非阻塞方式獲取子進(jìn)程執(zhí)行的返回值(習(xí)慣0表示正常結(jié)束)。若子進(jìn)程尚未完成時(shí)調(diào)用該方法,則會(huì)報(bào)異常`java.lang.IllegalThreadStateException`
int exitValue()      
// 以阻塞方式獲取子進(jìn)程執(zhí)行的返回值。若進(jìn)程尚未完成則會(huì)等待子進(jìn)程完成后才恢復(fù)當(dāng)前線程。
// 問(wèn)題:若子進(jìn)程無(wú)法正常關(guān)閉,則會(huì)導(dǎo)致Java線程一直掛起;
// 返回值為子進(jìn)程的退出碼
int waitFor()。                                  
// 如果超時(shí)前子進(jìn)程結(jié)束,那么返回`true` ,否則返回`false`
boolean waitFor(long timeout, TimeUnit unit)
// 強(qiáng)行終止子進(jìn)程,但調(diào)用后子進(jìn)程不會(huì)馬上被終止,所以立即調(diào)`boolean isAlive()`方法可能會(huì)返回`true`,因此需配合`waitFor`使用。
void destory()
// 默認(rèn)實(shí)現(xiàn)為調(diào)用`void destory()`方法。從JDK1.8開(kāi)始提供。
Process destoryForcibly()
// 如果子進(jìn)程還沒(méi)結(jié)束則返回`true` 。從JDK1.8開(kāi)始提供。                                          
boolean isAlive()
// 獲取子進(jìn)程的異常輸出流,如果子進(jìn)程以`ProcessBuilder`創(chuàng)建,且通過(guò)`ProcessBuilder.redirectError`設(shè)置重定向,那么該方法返回`null`                          
InputStream getErrorStream()
// 獲取子進(jìn)程的標(biāo)準(zhǔn)輸出流,如果子進(jìn)程以`ProcessBuilder`創(chuàng)建,且通過(guò)`ProcessBuilder.redirectOutput`設(shè)置重定向,那么該方法返回`null`
InputStream getInputStream() 
// 獲取子進(jìn)程的標(biāo)準(zhǔn)輸入流,如果子進(jìn)程以`ProcessBuilder`創(chuàng)建,且通過(guò)`ProcessBuilder.redirectInput`設(shè)置重定向,那么該方法返回`null`
OutputStream getOutputStream()

總結(jié)

到此這篇關(guān)于Java魔法堂:調(diào)用外部程序的文章就介紹到這了,更多相關(guān)Java調(diào)用外部程序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Jmeter對(duì)響應(yīng)數(shù)據(jù)實(shí)現(xiàn)斷言代碼實(shí)例

    Jmeter對(duì)響應(yīng)數(shù)據(jù)實(shí)現(xiàn)斷言代碼實(shí)例

    這篇文章主要介紹了Jmeter對(duì)響應(yīng)數(shù)據(jù)實(shí)現(xiàn)斷言代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • java中brew安裝rabbitmq以及簡(jiǎn)單實(shí)例

    java中brew安裝rabbitmq以及簡(jiǎn)單實(shí)例

    RabbitMQ是基于AMQP協(xié)議,由Erlang語(yǔ)言開(kāi)發(fā)的開(kāi)源消息隊(duì)列系統(tǒng),廣泛應(yīng)用于分布式系統(tǒng)中,用于應(yīng)用程序間的消息傳遞,它支持多種交換機(jī)類型,如直連交換機(jī)、扇形交換機(jī)和主題交換機(jī)等,能夠滿足不同的消息路由需求
    2024-10-10
  • mybatis plus 關(guān)聯(lián)數(shù)據(jù)庫(kù)排除不必要字段方式

    mybatis plus 關(guān)聯(lián)數(shù)據(jù)庫(kù)排除不必要字段方式

    這篇文章主要介紹了mybatis plus 關(guān)聯(lián)數(shù)據(jù)庫(kù)排除不必要字段方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • springmvc整合ssm配置的詳細(xì)代碼

    springmvc整合ssm配置的詳細(xì)代碼

    今天通過(guò)實(shí)例代碼給大家介紹了springmvc整合ssm配置的詳細(xì)方法,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-11-11
  • Java中Buffer緩沖區(qū)的ByteBuffer類詳解

    Java中Buffer緩沖區(qū)的ByteBuffer類詳解

    這篇文章主要介紹了Java中Buffer緩沖區(qū)的ByteBuffer類詳解,ByteBuffer類是Java NIO庫(kù)中的一個(gè)重要類,用于處理字節(jié)數(shù)據(jù),它提供了一種靈活的方式來(lái)讀取、寫(xiě)入和操作字節(jié)數(shù)據(jù),ByteBuffer類是一個(gè)抽象類,可以通過(guò)靜態(tài)方法創(chuàng)建不同類型的ByteBuffer對(duì)象,需要的朋友可以參考下
    2023-10-10
  • Java后端限制頻繁請(qǐng)求和重復(fù)提交的實(shí)現(xiàn)

    Java后端限制頻繁請(qǐng)求和重復(fù)提交的實(shí)現(xiàn)

    很多用戶會(huì)請(qǐng)求過(guò)于頻繁或者是多次重復(fù)提交數(shù)據(jù),本文主要介紹了Java后端限制頻繁請(qǐng)求和重復(fù)提交的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • SpringBoot?Validation提示信息國(guó)際化配置方式

    SpringBoot?Validation提示信息國(guó)際化配置方式

    這篇文章主要介紹了SpringBoot?Validation提示信息國(guó)際化配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 從實(shí)戰(zhàn)角度詳解Disruptor高性能隊(duì)列

    從實(shí)戰(zhàn)角度詳解Disruptor高性能隊(duì)列

    這篇文章主要介紹了從實(shí)戰(zhàn)角度詳解Disruptor高性能隊(duì)列,對(duì)正在學(xué)習(xí)這方面知識(shí)的小伙伴有很大的幫助,感興趣的小伙伴快來(lái)一起學(xué)習(xí)吧
    2021-08-08
  • Java從服務(wù)端下載Excel模板文件的兩種方法

    Java從服務(wù)端下載Excel模板文件的兩種方法

    這篇文章主要為大家詳細(xì)介紹了Java從服務(wù)端下載Excel模板文件的兩種方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • SpringBoot熱部署配置過(guò)程

    SpringBoot熱部署配置過(guò)程

    這篇文章主要介紹了SpringBoot熱部署配置過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03

最新評(píng)論