java调用外部程序(Runtime.getRuntime().exec)详解_java runtime.getruntime-程序员宅基地

技术标签: java  Java技术栈  

参考:https://blog.csdn.net/tiantang_1986/article/details/51219916

https://blog.csdn.net/km_moon/article/details/84751792

概述

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://"));

2,执行Runtime.exec()需要注意的陷阱:https://www.cnblogs.com/fpqi/p/9679039.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/footless_bird/article/details/116274515

智能推荐

leetcode 172. 阶乘后的零-程序员宅基地

文章浏览阅读63次。题目给定一个整数 n,返回 n! 结果尾数中零的数量。解题思路每个0都是由2 * 5得来的,相当于要求n!分解成质因子后2 * 5的数目,由于n中2的数目肯定是要大于5的数目,所以我们只需要求出n!中5的数目。C++代码class Solution {public: int trailingZeroes(int n) { ...

Day15-【Java SE进阶】IO流(一):File、IO流概述、File文件对象的创建、字节输入输出流FileInputStream FileoutputStream、释放资源。_outputstream释放-程序员宅基地

文章浏览阅读992次,点赞27次,收藏15次。UTF-8是Unicode字符集的一种编码方案,采取可变长编码方案,共分四个长度区:1个字节,2个字节,3个字节,4个字节。文件字节输入流:每次读取多个字节到字节数组中去,返回读取的字节数量,读取完毕会返回-1。注意1:字符编码时使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码。定义一个与文件一样大的字节数组,一次性读取完文件的全部字节。UTF-8字符集:汉字占3个字节,英文、数字占1个字节。GBK字符集:汉字占2个字节,英文、数字占1个字节。GBK规定:汉字的第一个字节的第一位必须是1。_outputstream释放

jeecgboot重新登录_jeecg 登录自动退出-程序员宅基地

文章浏览阅读1.8k次,点赞3次,收藏3次。解决jeecgboot每次登录进去都会弹出请重新登录问题,在utils文件下找到request.js文件注释这段代码即可_jeecg 登录自动退出

数据中心供配电系统负荷计算实例分析-程序员宅基地

文章浏览阅读3.4k次。我国目前普遍采用需要系数法和二项式系数法确定用电设备的负荷,其中需要系数法是国际上普遍采用的确定计算负荷的方法,最为简便;而二项式系数法在确定设备台数较少且各台设备容量差..._数据中心用电负荷统计变压器

HTML5期末大作业:网页制作代码 网站设计——人电影网站(5页) HTML+CSS+JavaScript 学生DW网页设计作业成品 dreamweaver作业静态HTML网页设计模板_网页设计成品百度网盘-程序员宅基地

文章浏览阅读7k次,点赞4次,收藏46次。HTML5期末大作业:网页制作代码 网站设计——人电影网站(5页) HTML+CSS+JavaScript 学生DW网页设计作业成品 dreamweaver作业静态HTML网页设计模板常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 明星、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 军事、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他 等网页设计题目, A+水平作业_网页设计成品百度网盘

【Jailhouse 文章】Look Mum, no VM Exits_jailhouse sr-iov-程序员宅基地

文章浏览阅读392次。jailhouse 文章翻译,Look Mum, no VM Exits!_jailhouse sr-iov

随便推点

chatgpt赋能python:Python怎么删除文件中的某一行_python 删除文件特定几行-程序员宅基地

文章浏览阅读751次。本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。作为通用的Aigc大模型,只是展现它原本的实力。对于颠覆工作方式的ChatGPT,应该选择拥抱而不是抗拒,未来属于“会用”AI的人。AI职场汇报智能办公文案写作效率提升教程 专注于AI+职场+办公方向。下图是课程的整体大纲下图是AI职场汇报智能办公文案写作效率提升教程中用到的ai工具。_python 删除文件特定几行

Java过滤特殊字符的正则表达式_java正则表达式过滤特殊字符-程序员宅基地

文章浏览阅读2.1k次。【代码】Java过滤特殊字符的正则表达式。_java正则表达式过滤特殊字符

CSS中设置背景的7个属性及简写background注意点_background设置背景图片-程序员宅基地

文章浏览阅读5.7k次,点赞4次,收藏17次。css中背景的设置至关重要,也是一个难点,因为属性众多,对应的属性值也比较多,这里详细的列举了背景相关的7个属性及对应的属性值,并附上演示代码,后期要用的话,可以随时查看,那我们坐稳开车了······1: background-color 设置背景颜色2:background-image来设置背景图片- 语法:background-image:url(相对路径);-可以同时为一个元素指定背景颜色和背景图片,这样背景颜色将会作为背景图片的底色,一般情况下设置背景..._background设置背景图片

Win10 安装系统跳过创建用户,直接启用 Administrator_windows10msoobe进程-程序员宅基地

文章浏览阅读2.6k次,点赞2次,收藏8次。Win10 安装系统跳过创建用户,直接启用 Administrator_windows10msoobe进程

PyCharm2021安装教程-程序员宅基地

文章浏览阅读10w+次,点赞653次,收藏3k次。Windows安装pycharm教程新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入下载安装PyCharm1、进入官网PyCharm的下载地址:http://www.jetbrains.com/pycharm/downl_pycharm2021

《跨境电商——速卖通搜索排名规则解析与SEO技术》一一1.1 初识速卖通的搜索引擎...-程序员宅基地

文章浏览阅读835次。本节书摘来自异步社区出版社《跨境电商——速卖通搜索排名规则解析与SEO技术》一书中的第1章,第1.1节,作者: 冯晓宁,更多章节内容可以访问云栖社区“异步社区”公众号查看。1.1 初识速卖通的搜索引擎1.1.1 初识速卖通搜索作为速卖通卖家都应该知道,速卖通经常被视为“国际版的淘宝”。那么请想一下,普通消费者在淘宝网上购买商品的时候,他的行为应该..._跨境电商 速卖通搜索排名规则解析与seo技术 pdf

推荐文章

热门文章

相关标签