【Java】解析Runtime.getRuntime().exec()方法的使用

时间:2021-10-16 20:30:27

在这篇文章中,笔者会阐述java中Runtime.getRuntime().exe()方法的使用。java提供可以调用系统脚本命令的实现。这里笔者使用的系统为windows系统,在下面的案例中,都是以window脚本命令来举例的。

exec()方法提供了几个重载版本,如下:

public Process exec(String command)----- 在单独的进程中执行指定的字符串命令。
public Process exec(String [] cmdArray)--- 在单独的进程中执行指定命令和变量
public Process exec(String command, String [] envp)---- 在指定环境的独立进程中执行指定命令和变量
public Process exec(String [] cmdArray, String [] envp)---- 在指定环境的独立进程中执行指定的命令和变量
public Process exec(String command,String[] envp,File dir)---- 在有指定环境和工作目录的独立进程中执行指定的字符串命令
public Process exec(String[] cmdarray,String[] envp,File dir)---- 在指定环境和工作目录的独立进程中执行指定的命令和变量

例如:

        1.RunTime.getRuntime().exec(String  command);
//在windows下相当于直接调用 /开始/搜索程序和文件 的指令,比如
Runtime.getRuntime().exec("notepad.exe"); //打开windows下记事本。

2.public Process exec(String [] cmdArray);
Runtime.getRuntime().exec(
new String[]{"/bin/sh","-c",command);//Linux下
Runtime.getRuntime().exec(new String[]{ "cmd", "/c",command});//Windows下

exec方法的返回值是一个Process类型的数据,通过这个返回值,通过这个返回值就可以获取到命令的执行信息。

Process的几种方法:
1.destroy():杀掉子进程
2.exitValue():返回子进程的出口值,值 0 表示正常终止
3.getErrorStream():获取子进程的错误流
4.getInputStream():获取子进程的输入流
5.getOutputStream():获取子进程的输出流
6.waitFor():导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程,根据惯例,0 表示正常终止

需要注意的是,在java中调用runtime线程执行脚本是非常消耗资源的,所以不要频繁调用。

需要说一说Process的waitFor方法,该方法的作用是等待子线程的结束。

例如:

Process p = Runtime.getRuntime().exec("notepad.exe");
p.waitFor();
System.out.println(
"--------------------------------------------我被执行了");//在手动关闭记事本软件后,才会被打印

需要注意,调用Runtime.getRuntime().exec()后,如果不及时捕捉进程的输出,会导致JAVA挂住,看似被调用进程没退出。所以,解决办法是,启动进程后,再启动两个JAVA线程及时的把被调用进程的输出截获。

【Java】解析Runtime.getRuntime().exec()方法的使用【Java】解析Runtime.getRuntime().exec()方法的使用
class StreamGobbler extends Thread {

InputStream is;
String type;

public StreamGobbler(InputStream is, String type) {
this.is = is;
this.type = type;
}

public void run() {
try {
InputStreamReader isr
= new InputStreamReader(is);
BufferedReader br
= new BufferedReader(isr);
String line
= null;
while ((line = br.readLine()) != null) {
if (type.equals("Error")) {
System.out.println(
"Error :" + line);
}
else {
System.out.println(
"Debug:" + line);
}
}
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
StreamGobbler.java

调用代码:

        try {
Process proc
= Runtime.getRuntime().exec("cmd /k start dir");
StreamGobbler errorGobbler
= new StreamGobbler(
proc.getErrorStream(),
"Error");
StreamGobbler outputGobbler
= new StreamGobbler(
proc.getInputStream(),
"Output");
errorGobbler.start();
outputGobbler.start();
proc.waitFor();
}
catch (Exception e) {
e.printStackTrace();
}

在实际的项目中,我们除了像上面那样调用,还会执行脚本文件。

    public static void main(String[] args) {
executeCommand(
"dir");
}
// 执行一个命令并返回相应的信息
public static void executeCommand(String command) {
try {
// 在项目根目录下将命令生成一份bat文件, 再执行该bat文件
File batFile = new File("dump.bat");
if (!batFile.exists())
batFile.createNewFile();
// 将命令写入文件中
FileWriter writer = new FileWriter(batFile);
writer.write(command);
writer.close();
// 执行该bat文件
Process process = Runtime.getRuntime().exec(
"cmd /c " + batFile.getAbsolutePath());
process.waitFor();
// 将bat文件删除
batFile.delete();
}
catch (Exception e) {
e.printStackTrace();
}
}

接下来,笔者要贴出cmd的一些命令参数:

cmd[[{/c|/k}][/s][/q][/d][{/a|/u}][/t:fg][/e:{on|off}][/f:{on|off}][/v:{on|off}]string]

参数
/c
执行string指定的命令,然后停止。
/k
执行string指定的命令并继续。
/s
修改位于/c或/k之后的string处理。
/q
关闭回显。
/d
禁用自动运行命令执行。
/a
创建美国国家标准协会(ANSI)输出。
/u
创建Unicode输出。
/t:fg
设置前景f和背景g的颜色。下表列出了可用作f和g的值的有效十六进制数字。值颜色
0黑色
1蓝色
2绿
3湖蓝色
4红
5紫色
6黄
7白色
8灰色
9浅蓝色
A浅绿色
B浅水绿
C浅红色
D浅紫色
E浅黄色
F亮白色

/e:on
启用命令扩展。
/e:off
禁用命令扩展。
/f:on
启用文件和目录名完成。
/f:off
禁用文件和目录名完成。
/v:on
启用延迟的环境变量扩展。
/v:off
禁用延迟的环境变量扩展。
string
指定要执行的命令。
/?
在命令提示符显示帮助。