目录
1、通过Runtime
2、通过ProcessBuilder
在java开发中,有时候需要与操作系统的命令行交互,执行特定的CMD命令或脚本。
我们有如下两种方式来实现:
Java的Runtime类和ProcessBuilder类都允许Java程序启动一个新的进程并执行特定的命令,通过标准输入输出流进行数据交换。Runtime类适用于简单的命令执行,ProcessBuilder类则更加灵活,适用于复杂的命令和参数传递。
1、通过Runtime
Runtime类提供了exec()方法来执行CMD命令。该方法接收一个String类型的命令字符串,并返回一个Process对象,通过这个对象可以获取命令执行的结果。
public static void runtimeExec() {
try {
// 调用CMD命令
String command = "jps -l";
Process process = Runtime.getRuntime().exec(command);
// 获取命令输出结果
InputStream inputStream = process.getInputStream();
// InputStream errorStream = process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK")); // 设置编码为GBK
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 等待命令执行完成
process.waitFor();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
输出结果如下
简单看下Runtime源码:
public Process exec(String command) throws IOException {
return exec(command, null, null);
}
public Process exec(String command, String[] envp, File dir)
throws IOException {
if (command.isEmpty())
throw new IllegalArgumentException("Empty command");
StringTokenizer st = new StringTokenizer(command);
String[] cmdarray = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++)
cmdarray[i] = st.nextToken();
return exec(cmdarray, envp, dir);
}
// 可以看到也是通过ProcessBuilder对象去start的
public Process exec(String[] cmdarray, String[] envp, File dir)
throws IOException {
return new ProcessBuilder(cmdarray)
.environment(envp)
.directory(dir)
.start();
}
2、通过ProcessBuilder
public static void processBuilder() throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "jps -l");
//设置环境变量,初始值是当前进程环境的一个副本System.getenv()
/* Map<String, String> env = pb.environment();
env.put("key", "value");*/
//设置工作目录
pb.directory(new File("E:\\study\\shell"));
//redirectErrorStream 属性默认值为false,意思是子进程的标准输出和错误输出被发送给两个独立的流,这些流可以通过 Process.getInputStream() 和 Process.getErrorStream() 方法来访问。
//如果将值设置为 true,标准错误将与标准输出合并。这使得关联错误消息和相应的输出变得更容易。
// 在此情况下,合并的数据可从 Process.getInputStream() 返回的流读取,而从 Process.getErrorStream() 返回的流读取将直接到达文件尾。
pb.redirectErrorStream(true);
/* File log = new File("E:\\study\\shell\\log.txt");
pb.redirectOutput(ProcessBuilder.Redirect.to(log));*/
//启动进程
Process process = pb.start();
// 获取命令输出结果
InputStream inputStream = process.getInputStream();
//InputStream errorStream = process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK")); // 设置编码为GBK
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 等待命令执行完成
process.waitFor();
}
输出结果:
当我们需要调用服务的某些脚本时,我们一般使用ProcessBuilder来调用,更加灵活