Java 执行 Windows 命令:最实用的几种写法与踩坑解决
在 Java 开发里,很多人都会碰到一个很常见的问题:怎么让 Java 程序去执行 Windows 命令。
比如打开记事本、查看 IP、复制文件、执行批处理脚本、关闭某个进程,甚至自动化处理系统任务,这些都离不开 Java 调用 Windows 命令。
这篇文章就围绕 “java 执行windows命令” 来讲清楚:
- Java 为什么能执行 Windows 命令
- 常用的写法有哪些
Runtime和ProcessBuilder怎么用- 如何获取命令输出
- 中文乱码、卡死、权限不足怎么解决
- 新手最容易踩的坑有哪些
一、问题分析:Java 为什么能执行 Windows 命令
Java 本身是跨平台语言,但它并不是“完全封闭”的。
在 Windows 系统里,Java 可以通过系统提供的进程调用能力,启动:
cmd.exepingipconfigtasklistcopyshutdown.bat批处理文件- 甚至一些第三方 exe 程序
也就是说,Java 程序不是直接“写进系统底层”,而是借助操作系统的命令行能力去完成任务。
常见应用场景有:
-
自动化运维
- 执行批处理脚本
- 远程调用系统命令
- 定时清理日志
-
桌面软件开发
- 打开文件夹、程序
- 查询系统信息
- 调用外部工具
-
服务器/管理工具
- 执行压缩、备份、同步
- 启动/停止服务
- 查看网络状态
二、最基础的写法:Runtime.exec()
这是很多人最早接触的方式。
1. 执行一条简单命令
public class TestCmd {
public static void main(String[] args) throws Exception {
Process process = Runtime.getRuntime().exec("cmd /c echo Hello Java");
int code = process.waitFor();
System.out.println("执行结束,返回码:" + code);
}
}
2. 这段代码是什么意思
Runtime.getRuntime():获取当前 Java 运行环境exec(...):执行外部命令cmd /c:让 Windows 通过命令行执行后面的命令,执行完就退出waitFor():等待命令执行结束code:返回码,0一般表示执行成功
三、推荐写法:ProcessBuilder 更稳、更灵活
如果你是稍微进阶一点的用户,建议优先用 ProcessBuilder。
因为它比 Runtime.exec() 更稳定,也更适合处理复杂命令、输出流、错误流。
1. 执行命令示例
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class TestProcessBuilder {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "ipconfig");
pb.redirectErrorStream(true);
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
int code = process.waitFor();
System.out.println("返回码:" + code);
}
}
2. 为什么更推荐它
- 参数可以分开写,不容易因为空格出错
- 可以更方便处理输入输出流
- 更适合执行复杂命令
- 可读性更高
四、执行 Windows 常见命令的实战写法
1. 执行 dir 查看目录
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "dir");
如果要查看指定目录:
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "dir C:\\Users\\Public");
2. 执行 ping
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "ping www.baidu.com");
适合做网络连通性检测。
3. 执行 ipconfig
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "ipconfig /all");
可以获取本机网卡、IP、DNS 等信息。
4. 关闭记事本进程
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "taskkill /f /im notepad.exe");
说明:
taskkill:结束任务/f:强制结束/im:按进程名结束
5. 关机命令
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "shutdown /s /t 60");
表示:60 秒后关机。
如果要取消关机:
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "shutdown /a");
6. 打开程序或文件
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start notepad");
或者打开某个文本文件:
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "start C:\\test\\a.txt");
注意:start 后面如果路径有空格,最好加双引号。
五、执行批处理文件 .bat
很多 Windows 自动化任务都写在 bat 文件里,Java 调用起来也很方便。
1. 直接执行 bat
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "D:\\script\\test.bat");
2. 如果 bat 文件路径有空格
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "\"D:\\my script\\test.bat\"");
3. 运行后等待结束
Process process = pb.start();
int code = process.waitFor();
System.out.println("bat 执行返回码:" + code);
六、如何获取命令执行结果
很多人执行命令后,只知道命令跑了,但不知道输出内容。
其实 Java 可以读取命令的标准输出流。
示例:读取命令输出
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class ReadCmdOutput {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "ipconfig");
pb.redirectErrorStream(true);
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
int code = process.waitFor();
System.out.println("命令执行完成,返回码:" + code);
}
}
重点说明
getInputStream():读取命令输出redirectErrorStream(true):把错误流合并到输出流,方便统一读取waitFor():避免程序过早退出
七、最常见的问题:中文乱码
这是 Java 执行 Windows 命令里最常见的坑之一。
1. 现象
命令输出中文时,控制台出现乱码,比如:
????- 一堆看不懂的字符
- 中文提示显示异常
2. 原因
Windows 命令行默认编码,和 Java 读取时使用的编码不一定一致。
特别是:
- Windows CMD 常见是 GBK
- Java 代码里如果直接用 UTF-8 去读,就容易乱码
3. 解决方案
方案一:按 GBK 读取
new InputStreamReader(process.getInputStream(), "GBK")
完整写法:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class CmdGBK {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "ipconfig");
pb.redirectErrorStream(true);
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), "GBK"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
process.waitFor();
}
}
方案二:在命令前切换编码页
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "chcp 65001 && echo 中文测试");
不过这个方式并不总是稳定,实际项目里更常见的还是根据系统编码读取。
八、命令卡死、程序不退出,怎么处理
有些人执行命令后,Java 程序一直卡着不结束。
这通常是因为:
- 只读取了输出流,没处理错误流
- 输出流缓冲区被塞满
waitFor()等待时,流没有及时消费- 命令本身会一直运行,比如
ping不加次数
1. 解决方法
方法一:合并错误流
pb.redirectErrorStream(true);
方法二:及时读取输出
不要等命令执行完再读,最好边执行边读。
方法三:给命令加限制
例如 ping 只执行 4 次:
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "ping 127.0.0.1 -n 4");
九、Java 执行 Windows 命令时的权限问题
有些命令不是普通用户权限就能执行的,比如:
- 修改系统配置
- 安装服务
- 结束某些受保护进程
- 操作某些目录
1. 常见现象
- 提示“拒绝访问”
- 命令执行失败
- 返回码不是 0
- 没有明显报错,但任务没完成
2. 解决办法
方案一:以管理员身份运行 Java 程序
如果你是用 IDE 运行,尝试:
- 右键 IDEA / Eclipse / 运行器
- 选择“以管理员身份运行”
方案二:检查命令本身权限
比如 taskkill 杀某些系统进程,普通权限不一定够。
方案三:操作受保护目录时换路径
不要直接写入 C:\Windows\System32 这类目录,优先使用:
D:\C:\Users\用户名\DesktopC:\Users\用户名\Documents
十、执行带空格路径的命令,怎么写才对
这是非常容易出错的点。
错误写法
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "C:\Program Files\test.exe");
这会因为空格导致识别失败。
正确写法
写法一:加引号
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "\"C:\\Program Files\\test.exe\"");
写法二:拆分参数
如果是直接执行 exe,建议这样:
ProcessBuilder pb = new ProcessBuilder("C:\\Program Files\\test.exe");
这时不要通过一整串命令传进去,减少转义问题。
十一、Runtime.exec() 和 ProcessBuilder 怎么选
1. 用 Runtime.exec() 的情况
适合:
- 简单命令
- 快速测试
- 临时脚本
例如:
Runtime.getRuntime().exec("cmd /c notepad");
2. 用 ProcessBuilder 的情况
适合:
- 正式项目
- 复杂命令
- 需要读取输出
- 需要控制工作目录
- 需要处理错误流
3. 实际建议
项目开发优先用 ProcessBuilder。
因为它更稳定,也更容易维护。
十二、一个完整的工具类写法
下面给你一个实用的 Java 执行 Windows 命令工具类,日常项目里可以直接改造使用。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
public class WindowsCmdUtil {
public static String execute(String command) {
StringBuilder result = new StringBuilder();
try {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", command);
pb.redirectErrorStream(true);
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), Charset.forName("GBK")))) {
String line;
while ((line = reader.readLine()) != null) {
result.append(line).append(System.lineSeparator());
}
}
int exitCode = process.waitFor();
result.append("exitCode=").append(exitCode);
} catch (Exception e) {
result.append("执行失败:").append(e.getMessage());
}
return result.toString();
}
public static void main(String[] args) {
String output = execute("ipconfig /all");
System.out.println(output);
}
}
十三、常见错误与排查思路
1. 命令能在 CMD 里执行,但 Java 里不行
优先检查:
- 路径是否有空格
- 是否少了引号
- 是否用了错误的转义符
- Java 读取编码是否正确
2. 返回码不是 0
说明命令执行失败,常见原因:
- 命令写错
- 参数格式不对
- 权限不足
- 目标文件不存在
- 依赖环境变量没配置
3. 输出为空
可能是:
- 命令没有标准输出
- 你读错了流
- 命令只输出到错误流
- 程序提前结束
建议合并错误流后再试。
4. 执行后没有反应
可能是:
- 命令被挂起
- 程序卡在等待输入
- 没有写
cmd /c - 目标程序需要图形界面,但后台启动方式不对
十四、实际项目里的使用建议
新手建议
先记住这三个关键点:
- Windows 命令前面一般加
cmd /c - 优先用
ProcessBuilder - 中文输出多半要处理编码
进阶建议
如果是项目开发,尽量封装成统一工具类,支持:
- 命令执行
- 输出读取
- 错误日志
- 超时控制
- 返回码判断
专业建议
对于生产环境,最好增加:
- 超时终止机制
- 日志记录
- 权限检查
- 命令白名单
- 参数过滤,防止命令注入
十五、注意事项
1. 不要直接拼接用户输入
如果命令参数来自网页、表单、接口,一定要小心命令注入问题。
比如用户输入了恶意字符:
&|&&;
很可能导致执行额外命令。
2. 尽量避免执行过长命令
命令越长,越容易出现转义和兼容问题。
建议先写成 bat 脚本,再由 Java 调用。
3. 复杂场景用脚本更稳
如果要做一串复杂操作,比如:
- 检查网络
- 备份文件
- 压缩目录
- 删除旧日志
推荐先写批处理脚本,再由 Java 触发。
4. 注意系统差异
不同 Windows 版本在权限、编码、命令细节上会有差别。
老机器、精简系统、英文系统尤其容易出问题。
十六、总结
Java 执行 Windows 命令,本质上就是通过系统进程去调用 cmd.exe、批处理文件或外部程序。
如果只是简单命令,Runtime.exec() 能用;如果是正式项目、复杂命令、需要输出控制,更推荐 ProcessBuilder。
最实用的经验可以记成三句话:
- 能拆参数就别整串拼命令
- 能用
ProcessBuilder就别只靠Runtime.exec() - 遇到中文乱码,优先查编码,Windows 下常见是 GBK
掌握这套方法后,Java 调用 Windows 命令、执行脚本、自动化处理系统任务就会顺手很多。

还没有评论,来说两句吧...