java使用Runtime.getRuntime().exec調(diào)用外部程序
概述
Runtime.getRuntime().exec 用于調(diào)用外部可執(zhí)行程序或系統(tǒng)命令,并重定向外部程序的標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤到緩沖池。功能和windows“運(yùn)行”類似。
格式:
Process process = Runtime.getRuntime().exec( ".//p.exe "); process.waitfor();
第一行的“.//p.exe”是要執(zhí)行的程序名,Runtime.getRuntime() 返回當(dāng)前應(yīng)用程序的Runtime對(duì)象,該對(duì)象的 exec() 方法指示Java虛擬機(jī)創(chuàng)建一個(gè)子進(jìn)程執(zhí)行指定的可執(zhí)行程序,并返回與該子進(jìn)程對(duì)應(yīng)的Process對(duì)象實(shí)例。通過(guò)Process可以控制該子進(jìn)程的執(zhí)行或獲取該子進(jìn)程的信息。
第二條語(yǔ)句的目的等待子進(jìn)程完成再往下執(zhí)行。
方法API
Runtime.getRuntime().exec共有六個(gè)重載方法:
// 在單獨(dú)的進(jìn)程中執(zhí)行指定的外部可執(zhí)行程序的啟動(dòng)路徑或字符串命令
public Process exec(String command)
// 在單獨(dú)的進(jìn)程中執(zhí)行指定命令和變量
public Process exec(String[] cmdArray)
// 在指定環(huán)境的獨(dú)立進(jìn)程中執(zhí)行指定命令和變量
public Process exec(String command, String[] envp)
// 在指定環(huán)境的獨(dú)立進(jìn)程中執(zhí)行指定的命令和變量
public Process exec(String[] cmdArray, String[] envp)
// 在指定環(huán)境和工作目錄的獨(dú)立進(jìn)程中執(zhí)行指定的字符串命令
public Process exec(String command, String[] envp, File dir)
// 在指定環(huán)境和工作目錄的獨(dú)立進(jìn)程中執(zhí)行指定的命令和變量
public Process exec(String[] cmdarray, String[] envp, File dir)
// 參數(shù)說(shuō)明:
cmdarray // 包含所調(diào)用命令及其參數(shù)的數(shù)組。數(shù)組第一個(gè)元素是命令,其余是參數(shù)
envp // 字符串?dāng)?shù)組,其中每個(gè)元素的環(huán)境變量的設(shè)置格式為 name=value,如果子進(jìn)程應(yīng)該繼承當(dāng)前進(jìn)程的環(huán)境,則該參數(shù)為null
dir // 子進(jìn)程的工作目錄;如果子進(jìn)程應(yīng)該繼承當(dāng)前進(jìn)程的工作目錄,則該參數(shù)為null
// 參數(shù)cmdArray 示例:shutdown -s -t 3600
String arr[] = {"shutdown","-s","-t","3600"};
Process process = Runtime.getRuntime().exec(arr[]);
/*
注意:
在調(diào)用這個(gè)方法時(shí),不能將命令和參數(shù)放在一起,eg:String arr[] = {"shutdown -s -t 3600"};
這樣會(huì)導(dǎo)致程序把“shutdown -s -t 3600”當(dāng)成是一條命令的名稱,然后去查找“shutdown -s -t 3600”這條命令,它當(dāng)然會(huì)找不到,所以就會(huì)報(bào)錯(cuò)
*/
注意:
Runtime.exec() 不是cmd或shell環(huán)境,因此無(wú)法直接調(diào)用dir等命令,需要在程序中讀取運(yùn)行的操作系統(tǒng)平臺(tái),以調(diào)用不同的命令解釋器(NT:cmd.exe,windows 95/98:command.exe,linux:/bin/sh)
Procss類將持有該程序返回 Java VM 的引用。這個(gè)procss類是一個(gè)抽象類,具體子類的實(shí)現(xiàn)依賴于不同的底層操作系統(tǒng)。
Process 的常用方法:
// 導(dǎo)致當(dāng)前線程等待,如有必要,一直要等到由該 Process 對(duì)象表示的進(jìn)程已經(jīng)終止。 int waitFor() /* 如果已終止該子進(jìn)程,此方法立即返回。 如果沒(méi)有終止該子進(jìn)程,調(diào)用的線程將被阻塞,直到退出子進(jìn)程,0 表示正常終止 */ // 殺掉子進(jìn)程 void destroy() // 返回子進(jìn)程的出口值,值 0 表示正常終止 int exitValue() // 獲取子進(jìn)程的錯(cuò)誤流 InputStream getErrorStream() // 獲取子進(jìn)程的輸入流 InputStream getInputStream() // 獲取子進(jìn)程的輸出流 OutputStream getOutputStream()
程序阻塞問(wèn)題
通過(guò) Process實(shí)例.getInputStream() 和 Process實(shí)例.getErrorStream() 獲取的輸入流和錯(cuò)誤信息流是緩沖池向當(dāng)前Java程序提供的,而不是直接獲取外部程序的標(biāo)準(zhǔn)輸出流和標(biāo)準(zhǔn)錯(cuò)誤流。

而緩沖池的容量是一定的,因此若外部程序在運(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é)束后需自動(dòng)關(guān)閉,否則不管是字符流還是字節(jié)流均由于既讀不到數(shù)據(jù),又讀不到流結(jié)束符,從而出現(xiàn)阻塞Java進(jìn)程運(yùn)行的情況。cmd的參數(shù) “/c” 表示當(dāng)命令執(zhí)行完成后關(guān)閉自身。
實(shí)例
在當(dāng)前目錄執(zhí)行dir命令,并將結(jié)果保存到 c:\dir.txt 文本文件中:
前提:假設(shè)當(dāng)前用戶的家目錄為c:\user\fsjohnhuang
c:\user\fsjohnhuang下的目錄結(jié)構(gòu)
c:\user\fsjohnhuang
|--jottings
|--test.txt
d:\test下的目錄結(jié)構(gòu)
d:\test
|--movies
|--readme.txt
代碼片段
Runtime r = Runtime.getRuntime();
try{
Process proc = r.exec("cmd /c dir > %dest%", new String[]{"dest=c:\\dir.txt", new File("d:\\test")});
int exitVal = proc.waitFor(); // 阻塞當(dāng)前線程,并等待外部程序中止后獲取結(jié)果碼
System.out.println(exitVal == 0 ? "成功" : "失敗");
}
catch(Exception e){
e.printStackTrace();
}
執(zhí)行代碼后查看c:\dir.txt文件內(nèi)容如如下:
驅(qū)動(dòng)器 D 中的卷沒(méi)有標(biāo)簽。
卷的序列號(hào)是 8074-B214
D:\test 的目錄
2014/09/22 14:45 <DIR> movies
2014/03/31 17:14 8,642 readme.txt
拓展
1,調(diào)用一次exec方法執(zhí)行多條cmd命令,使用 && 分隔命令,該方法的局限性是只能在cmd里面使用
Runtime.getRuntime().exec("cmd /c set CLASSPATH=D:\\ && javac D:\\a.java && java a");
// 方法重載:public Process exec(String[] cmdarray, String[] envp, File dir)
String arr[] = {"CLASSPATH=D://","Path=C:\\Program Files\\Java\\jdk1.8.0_131\\bin"};
Runtime.getRuntime().exec("cmd /c javac a.java && java a", arr, new File("D://"));2.執(zhí)行Runtime.exec()需要注意的陷阱
作為Java語(yǔ)言的一部分。java.lang包被隱藏的導(dǎo)入到每一個(gè)Java程序。這個(gè)包的表面陷阱,經(jīng)常影響到大多數(shù)程序員。這個(gè)月,我將討論運(yùn)行時(shí)exec()方法時(shí)的潛伏陷阱。
1.當(dāng)運(yùn)行exec()時(shí)不會(huì)執(zhí)行命令
java.lang.Runtime類,突出了靜態(tài)方法calledgetRuntime(),,它會(huì)檢索當(dāng)前的Java運(yùn)行時(shí)環(huán)境。這是唯一的方法來(lái)獲取Runtime對(duì)象的引用。獲取該引用,您通過(guò)可以調(diào)用Runtime類的exec()方法運(yùn)行外部程序。開(kāi)發(fā)人員經(jīng)常調(diào)用這個(gè)方法來(lái)啟動(dòng)瀏覽器顯示一個(gè)HTML幫助頁(yè)面。
exec()有四個(gè)重載:
public Process exec(String command); public Process exec(String [] cmdArray); public Process exec(String command, String [] envp); public Process exec(String [] cmdArray, String [] envp);
對(duì)于每個(gè)這樣的方法,都會(huì)產(chǎn)生一個(gè)命令,并可能攜帶一組參數(shù)——被傳遞給一個(gè)特定操作系統(tǒng)的函數(shù)調(diào)用。這隨后創(chuàng)建一個(gè)特定操作系統(tǒng)的進(jìn)程(一個(gè)運(yùn)行著的程序),procss類將持有該程序返回Java VM的引用。這個(gè)procss類是一個(gè)抽象類,具體子類的實(shí)現(xiàn)依賴于不同的底層操作系統(tǒng)。
你可以通過(guò)三種可能的輸入?yún)?shù)到這些方法:
1、一個(gè)字符串,表示程序執(zhí)行和程序的任何參數(shù)。
2、一個(gè)字符串?dāng)?shù)組,通過(guò)參數(shù)來(lái)區(qū)分出程序的實(shí)現(xiàn)功能。
3、一個(gè)環(huán)境變量的數(shù)組
傳遞環(huán)境變量是,使用格式化的方式:名稱=值。如果你使用單個(gè)字符串和它的參數(shù)的方式調(diào)用exec()的重載,,注意字符串是通過(guò)StringTokenizer類被解析,使用空格作為分隔符。
2.陷入 IllegalThreadStateException
運(yùn)行exec()的第一個(gè)陷阱,是theIllegalThreadStateException。 普遍上,第一次對(duì)api的嘗試,都是基于一些最常用的方法。例如,執(zhí)行一個(gè)java vm的外部過(guò)程,我們使用exec()方法。查看外部過(guò)程的返回值,我們使用process類的exitValue()方法??吹降闹低獠窟^(guò)程的回報(bào),我們使用exitValue()方法在過(guò)程類。在我們的第一個(gè)示例中,我們將嘗試執(zhí)行Java編譯器(javac exe)。
清單 4.1 BadExecJavac.java
import java.util.*;
import java.io.*;
public class BadExecJavac
{
public static void main(String args[])到此這篇關(guān)于java使用Runtime.getRuntime().exec調(diào)用外部程序的文章就介紹到這了,更多相關(guān)java調(diào)用外部程序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java編程中快速排序算法的實(shí)現(xiàn)及相關(guān)算法優(yōu)化
這篇文章主要介紹了Java編程中快速排序算法的實(shí)現(xiàn)及相關(guān)算法優(yōu)化,快速排序算法的最差時(shí)間復(fù)雜度為(n^2),最優(yōu)時(shí)間復(fù)雜度為(n\log n),存在優(yōu)化的空間,需要的朋友可以參考下2016-05-05
java EasyExcel面向Excel文檔讀寫(xiě)邏輯示例詳解
這篇文章主要為大家介紹了java EasyExcel面向Excel文檔讀寫(xiě)邏輯示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Java確保MQ消息隊(duì)列不丟失的實(shí)現(xiàn)與流程分析
在分布式系統(tǒng)中,消息隊(duì)列是核心組件之一,本文將探討如何確保MQ消息隊(duì)列不丟失,并通過(guò)Java代碼示例和流程圖來(lái)演示解決方案,需要的可以了解下2025-05-05
Java編程通過(guò)匹配合并數(shù)據(jù)實(shí)例解析(數(shù)據(jù)預(yù)處理)
這篇文章主要介紹了Java編程通過(guò)匹配合并數(shù)據(jù)實(shí)例解析(數(shù)據(jù)預(yù)處理),分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01
MyBatis使用Map與POJO類實(shí)現(xiàn)CRUD操作的步驟詳解
本文將通過(guò)實(shí)際案例,詳細(xì)講解在MyBatis中如何使用Map集合和POJO類兩種方式實(shí)現(xiàn)數(shù)據(jù)庫(kù)的增刪改查操作,解決常見(jiàn)映射問(wèn)題,提高開(kāi)發(fā)效率,需要的朋友可以參考下2025-12-12
Java實(shí)現(xiàn)查找當(dāng)前字符串最大回文串代碼分享
本文給大家介紹的是如何使用Java實(shí)現(xiàn)查找當(dāng)前字符串最大回文串代碼,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下2016-07-07
Java中Scanner的使用及nextLine和nextInt等混用報(bào)錯(cuò)解決方案
Scanner類用于從控制臺(tái)輸入數(shù)據(jù),常用方法包括next()、nextLine()、nextInt()、nextDouble()和nextBoolean(),案例測(cè)試和常見(jiàn)錯(cuò)誤情況分析表明,nextDouble等方法不會(huì)跳過(guò)空格和回車(chē),而nextLine會(huì)讀取整行并跳到下一行2026-03-03
Java concurrency之Condition條件_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
Condition的作用是對(duì)鎖進(jìn)行更精確的控制。下面通過(guò)本文給大家分享Java concurrency之Condition條件的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-06-06
java實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證(包含前端代碼)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12

