在Java中执行DOS命令(通常指Windows系统的命令行指令)是系统交互、自动化脚本或外部程序调用的常见需求,Java提供了两种核心方式:Runtime.exec() 和 ProcessBuilder 类,以下将详细说明实现步骤、注意事项及最佳实践。
使用 Runtime.exec()(传统方法)
Runtime 类提供exec()方法直接执行命令,适用于简单场景。
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class RunDOSCommand {
public static void main(String[] args) {
try {
// 执行命令(获取IP配置)
Process process = Runtime.getRuntime().exec("ipconfig");
// 读取命令输出
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), "GBK") // Windows中文环境用GBK编码
);
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 等待命令执行完成并检查退出码
int exitCode = process.waitFor();
System.out.println("Exit Code: " + exitCode); // 0表示成功
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用 ProcessBuilder(推荐方法)
ProcessBuilder 提供更灵活的参数控制(如目录设置、环境变量),支持命令拆分,避免注入风险。
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ProcessBuilderExample {
public static void main(String[] args) {
try {
// 构建命令(按空格拆分参数)
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "ping", "www.baidu.com");
builder.redirectErrorStream(true); // 合并错误流到输入流
// 启动进程
Process process = builder.start();
// 读取输出
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), "GBK"))
) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// 检查执行结果
int exitCode = process.waitFor();
System.out.println("Exit Code: " + exitCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
关键注意事项
-
命令注入风险
错误做法:拼接用户输入作为命令(如exec("ping " + userInput))。
正确做法:使用ProcessBuilder拆分参数,自动处理特殊字符:ProcessBuilder builder = new ProcessBuilder("ping", userInput); // 安全 -
编码问题
Windows中文环境默认使用GBK编码,需显式指定以避免乱码:new InputStreamReader(process.getInputStream(), "GBK")
-
阻塞与超时控制
使用waitFor(long timeout, TimeUnit unit)防止命令卡死:if (!process.waitFor(30, TimeUnit.SECONDS)) { process.destroy(); // 超时终止进程 } -
跨平台兼容性
- Windows需通过
cmd.exe /c执行命令(如cmd.exe /c dir)。 - Linux/Mac使用
/bin/sh -c。
- Windows需通过
-
资源释放
关闭流释放资源:try (BufferedReader reader = ...) { ... } // 自动关闭
常见问题解决方案
-
如何获取命令执行的错误信息?
读取错误流:BufferedReader errorReader = new BufferedReader( new InputStreamReader(process.getErrorStream()) ); -
如何执行多条命令?
通过&&连接命令(仅限Windows):ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "dir && ipconfig"); -
如何指定工作目录?
使用ProcessBuilder.directory():builder.directory(new File("C:\\myfolder"));
- 简单命令:优先选
Runtime.exec(),代码简洁。 - 复杂场景:必须用
ProcessBuilder,保障安全性和灵活性。 - 生产环境建议:
- 严格校验用户输入。
- 添加超时机制和日志监控。
- 考虑使用
Apache Commons Exec等工具库简化流程。
引用说明参考自Oracle官方文档 ProcessBuilder 和 Runtime,并结合Java安全编码实践编写。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/7804.html