Runtime.getRuntime().exec详解
citgpt 2024-10-25 11:50 19 浏览 0 评论
Runtime.getRuntime().exec详解
概述
Runtime.getRuntime().exec 用于调用外部可执行程序或系统命令,并重定向外部程序的标准输入、标准输出和标准错误到缓冲池。功能和windows“运行”类似。
格式:
Process process = Runtime.getRuntime().exec( ".//p.exe ");
process.waitfor();
第一行的“.//p.exe”是要执行的程序名,Runtime.getRuntime() 返回当前应用程序的Runtime对象,该对象的 exec() 方法指示Java虚拟机创建一个子进程执行指定的可执行程序,并返回与该子进程对应的Process对象实例。通过Process可以控制该子进程的执行或获取该子进程的信息。
第二条语句的目的等待子进程完成再往下执行。
方法API
Runtime.getRuntime().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)
// 参数说明:
cmdarray // 包含所调用命令及其参数的数组。数组第一个元素是命令,其余是参数
envp // 字符串数组,其中每个元素的环境变量的设置格式为 name=value,如果子进程应该继承当前进程的环境,则该参数为null
dir // 子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为null
// 参数cmdArray 示例:shutdown -s -t 3600
String arr[] = {"shutdown","-s","-t","3600"};
Process process = Runtime.getRuntime().exec(arr[]);
/*
注意:
在调用这个方法时,不能将命令和参数放在一起,eg:String arr[] = {"shutdown -s -t 3600"};
这样会导致程序把“shutdown -s -t 3600”当成是一条命令的名称,然后去查找“shutdown -s -t 3600”这条命令,它当然会找不到,所以就会报错
*/
注意:Runtime.exec() 不是cmd或shell环境,因此无法直接调用dir等命令,需要在程序中读取运行的操作系统平台,以调用不同的命令解释器(NT:cmd.exe,windows 95/98:command.exe,linux:/bin/sh)
Procss类将持有该程序返回 Java VM 的引用。这个procss类是一个抽象类,具体子类的实现依赖于不同的底层操作系统。
Process 的常用方法:
// 导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。
int waitFor()
/* 如果已终止该子进程,此方法立即返回。
如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程,0 表示正常终止 */
// 杀掉子进程
void destroy()
// 返回子进程的出口值,值 0 表示正常终止
int exitValue()
// 获取子进程的错误流
InputStream getErrorStream()
// 获取子进程的输入流
InputStream getInputStream()
// 获取子进程的输出流
OutputStream getOutputStream()
程序阻塞问题
通过 Process实例.getInputStream() 和 Process实例.getErrorStream() 获取的输入流和错误信息流是缓冲池向当前Java程序提供的,而不是直接获取外部程序的标准输出流和标准错误流。
而缓冲池的容量是一定的,因此若外部程序在运行过程中不断向缓冲池输出内容,当缓冲池填满,那么外部程序将暂停运行直到缓冲池有空位可接收外部程序的输出内容为止。(采用xcopy命令复制大量文件时将会出现该问题)
解决办法:当前的Java程序不断读取缓冲池的内容,从而为腾出缓冲池的空间。
Runtime r = Runtime.getRuntime();
try {
Process proc = r.exec("cmd /c dir"); // 假设该操作为造成大量内容输出
// 采用字符流读取缓冲池内容,腾出空间
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream(), "gbk")));
String line = null;
while ((line = reader.readLine()) != null){
System.out.println(line);
}
/* 或采用字节流读取缓冲池内容,腾出空间
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();
}
注意:外部程序在执行结束后需自动关闭,否则不管是字符流还是字节流均由于既读不到数据,又读不到流结束符,从而出现阻塞Java进程运行的情况。cmd的参数 “/c” 表示当命令执行完成后关闭自身。
实例
在当前目录执行dir命令,并将结果保存到 c:\dir.txt 文本文件中:
前提:假设当前用户的家目录为c:\user\fsjohnhuang
c:\user\fsjohnhuang下的目录结构
c:\user\fsjohnhuang
|--jottings
|--test.txt
d:\test下的目录结构
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(); // 阻塞当前线程,并等待外部程序中止后获取结果码
System.out.println(exitVal == 0 ? "成功" : "失败");
} catch(Exception e) {
e.printStackTrace();
}
执行代码后查看c:\dir.txt文件内容如如下:
驱动器 D 中的卷没有标签。
卷的序列号是 8074-B214
D:\test 的目录
2014/09/22 14:45 <DIR> movies
2014/03/31 17:14 8,642 readme.txt
拓展
1,调用一次exec方法执行多条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://"));<em id="__mceDel" style="background-color: rgba(255, 255, 255, 1); font-family: "PingFang SC", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px"> </em>
2,执行Runtime.exec()需要注意的陷阱
相关推荐
- js中arguments详解
-
一、简介了解arguments这个对象之前先来认识一下javascript的一些功能:其实Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数...
- firewall-cmd 常用命令
-
目录firewalldzone说明firewallzone内容说明firewall-cmd常用参数firewall-cmd常用命令常用命令 回到顶部firewalldzone...
- epel-release 是什么
-
EPEL-release(ExtraPackagesforEnterpriseLinux)是一个软件仓库,它为企业级Linux发行版(如CentOS、RHEL等)提供额外的软件包。以下是关于E...
- FullGC详解 什么是 JVM 的 GC
-
前言:背景:一、什么是JVM的GC?JVM(JavaVirtualMachine)。JVM是Java程序的虚拟机,是一种实现Java语言的解...
-
2024-10-26 08:50 citgpt
- 跨域(CrossOrigin)
-
1.介绍 1)跨域问题:跨域问题是在网络中,当一个网络的运行脚本(通常时JavaScript)试图访问另一个网络的资源时,如果这两个网络的端口、协议和域名不一致时就会出现跨域问题。 通俗讲...
- 微服务架构和分布式架构的区别
-
1、含义不同微服务架构:微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并...
- 深入理解与应用CSS clip-path 属性
-
clip-pathclip-path是什么clip-path 是一个CSS属性,允许开发者创建一个剪切区域,从而决定元素的哪些部分可见,哪些部分会被隐...
-
2024-10-25 11:51 citgpt
- Request.ServerVariables 大全
-
Request.ServerVariables("Url")返回服务器地址Request.ServerVariables("Path_Info")客户端提供的路...
- python操作Kafka
-
目录一、python操作kafka1.python使用kafka生产者2.python使用kafka消费者3.使用docker中的kafka二、python操作kafka细...
- Runtime.getRuntime().exec详解
-
Runtime.getRuntime().exec详解概述Runtime.getRuntime().exec用于调用外部可执行程序或系统命令,并重定向外部程序...
-
2024-10-25 11:50 citgpt
- promise.all详解 promise.all是干什么的
-
promise.all详解promise.all中所有的请求成功了,走.then(),在.then()中能得到一个数组,数组中是每个请求resolve抛出的结果...
-
2024-10-24 16:21 citgpt
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracleclient (56)
- springbatch (59)
- oracle恢复数据 (56)
- 简单工厂模式 (68)
- 函数指针 (72)
- fill_parent (135)
- java配置环境变量 (140)
- linux文件系统 (56)
- 计算机操作系统教程 (60)
- 静态ip (63)
- notifyicon (55)
- 线程同步 (58)
- xcode 4 5 (60)
- 调试器 (60)
- c0000005 (63)
- html代码大全 (61)
- header utf 8 (61)
- 多线程多进程 (65)
- require_once (60)
- 百度网盘下载速度慢破解方法 (72)
- 谷歌浏览器免费入口 (72)
- npm list (64)
- 网站打开速度检测 (59)
- 网站建设流程图 (58)
- this关键字 (67)