Java执行系统命令策略
通过Java执行系统命令,与cmd中或者终端上一样执行shell命令一样。
最典型的用法:
1、Runtime.getRuntime().exec();会在给定的环境和工作目录下启动一个独立的进程运行外部命令。
2、new ProcessBuilder(cmdArray).start();
从JDK1.5开始,官方提供并推荐使用ProcessBuilder类进行shell命令操作。
首先介绍Runtime类提供了如下方法:
public long totalMemory();//返回所有可用内存空间
public long maxMemory();//返回最大可用内存空间
public long freeMemory();//返回空余内存空间
public void gc();(如果内存东西过大)手动实现JVM的gc机制。
public Process exec(String command)throws IOException//执行外部命令
Runtime.getRuntime().availableProcessors();//返回jvm可用的处理器数量
Runtime常见的几个重写的参数方法:
public Process exec(String command) throws IOExceptionpublic Process exec(String cmdarray[]) throws IOExceptionpublic Process exec(String command, String[] envp) throws IOExceptionpublic Process exec(String command, String[] envp, File dir) throws IOExceptionpublic Process exec(String[] cmdarray, String[] envp) throws IOExceptionpublic Process exec(String[] cmdarray, String[] envp, File dir) throws IOException
对上面进行解释:
1、command:一个命令,可能包含参数和命令
2、envp:环境变量的设置;格式(name=value,name=null),null表示子进程继承当前的运行时的环境。
3、dir:子进程工作目录,null表示继承当前进程的工作目录
4、cmdarray:包含多个命令的数组,可以是命令也可以是参数
简单实现:
import java.io.BufferedReader;
import java.io.InputStreamReader;import org.junit.Test;public class Demo {@Testpublic void testName() throws Exception {// 调用命令Runtime runtime = Runtime.getRuntime();Process process = null;
try{process = runtime.exec("javac"); // 用法1:调用一个外部程序// process = runtime.exec("cmd /c dir"); // 用法2:调用一个指令(可包含参数)// process = runtime.exec("cmd /c test.bat", null, new File("D:\\test.test.bat")); // 用法3:调用一个.bat文件或者exe文件// 存放要输出的行数据String line = null;// 输出返回的报错信息System.out.println("=================ErrorStream===================");BufferedReader inErr = new BufferedReader(new InputStreamReader(process.getErrorStream()));while ((line = inErr.readLine()) != null) {System.out.println(line);}// 输出正常的返回信息System.out.println("=================InputStream===================");BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));while ((line = in.readLine()) != null) {System.out.println(line);}// 获取退出码int exitVal = process.waitFor(); // 等待进程运行结束//如果返回0表示执行成功,返回1表示在还行失败System.out.println("exitVal = " + exitVal);} catch (Exception e) {e.printStackTrace();}finally{if (process != null) {process.destroy();}}}
}
使用Process.waitFor()
和Process.exitValue()的区别:
Process.waitFor()
与Process.exitValue()
同样会返回外部程序的执行结果,但是exitValue()
会阻塞直到外部程序运行结束。
指令介绍:
cmd /c dir 是执行完dir命令后关闭命令窗口。
cmd /k dir 是执行完dir命令后不关闭命令窗口。
cmd /c start dir 会打开一个新窗口后执行dir指令,原窗口会关闭。
cmd /k start dir 会打开一个新窗口后执行dir指令,原窗口不会关闭。
Runtime.exec()
不是一个命令行工具:相对于系统命令行工具,Runtime.exec(..)
会更加局限并且不具备跨平台功能,命令行能接收的任意字符串,Runtime.exec(..)
并不一定能接收。这个陷阱通常出现在Runtime.exec(String)
这个接收单个字符串执行外部命令的方法中。造成这个混乱的原因之一在于Runtime.exec(String)
将传递的字符串作为外部命令的参数,而命令行中可以区分一个字符串中的多个命令。
如何解决?
就是把jechoHTT类里面输出的内容,保存到test.txt
public class CommandLineExec {public static void main(String[] args) throws IOException, InterruptedException {FileOutputStream fos = new FileOutputStream("test.txt");Process pid = Runtime.getRuntime().exec("java Test$jechoHTT");new Thread(new OutputHandlerRunnable(pid.getInputStream(), fos)).start();new Thread(new OutputHandlerRunnable(pid.getErrorStream())).start();int exitValue = pid.waitFor();System.out.println("Process exitValue: " + exitValue);fos.flush();fos.close();}private static class OutputHandlerRunnable implements Runnable {private InputStream in;private OutputStream os;public OutputHandlerRunnable(InputStream in) {this.in = in;}// add redirectpublic OutputHandlerRunnable(InputStream in, OutputStream redirect) {this(in);this.os = redirect;}@Overridepublic void run() {try (BufferedReader bufr = new BufferedReader(new InputStreamReader(this.in))) {PrintWriter pw = null;if (this.os != null) {pw = new PrintWriter(this.os);}String line = null;while ((line = bufr.readLine()) != null) {System.out.println(line);if (pw != null) {// redirectpw.println(line);}}if (pw != null) {pw.flush();}} catch (IOException e) {e.printStackTrace();}}}private static class jechoHTT {public static void main(String[] args) {System.out.println("Hello World!!!");}}
}
我们在介绍一下ProcessBuilder这个方法执行外部命令:
优点:配置环境变量时更优雅、对当前目录的控制也更合理、错误流重定向特别方便 、进程控制更简洁。
ProcessBuilder基本方法介绍:
构造方法摘要ProcessBuilder(List<String> command)利用指定的操作系统程序和参数构造一个进程生成器。ProcessBuilder(String... command)利用指定的操作系统程序和参数构造一个进程生成器。方法摘要command()返回此进程生成器的操作系统程序和参数。command(List<String> command)设置此进程生成器的操作系统程序和参数。command(String... command)设置此进程生成器的操作系统程序和参数。directory()返回此进程生成器的工作目录。directory(File directory)设置此进程生成器的工作目录。environment()返回此进程生成器环境的字符串映射视图。redirectErrorStream()通知进程生成器是否合并标准错误和标准输出。redirectErrorStream(boolean redirectErrorStream)设置此进程生成器的 redirectErrorStream 属性。start()使用此进程生成器的属性启动一个新进程。
基本用法:
public class ProcessTool {public static void main(String[] args) throws IOException {execWindowCmd();}public static void execWindowCmd() throws IOException {ProcessBuilder pb = new ProcessBuilder();// 命令Map<String, String> env = pb.environment();// 独立环境变量System.out.println(env);// 打印环境变量env.put("MY_NAME", "KING");// 添加环境变量key-valuepb.redirectErrorStream(true);// 重定向错误输出流到正常输出流try {pb.directory(new File("d://test1"));// 设置目录test1pb.command("cmd", "/c", "dir");// 执行命令Process process1;process1 = pb.start();// 启动进程BufferedReader br1;br1 = new BufferedReader(new InputStreamReader(process1.getInputStream(), "gbk"));String line1 = null;while ((line1 = br1.readLine()) != null) {System.out.println(line1);}pb.directory(new File("d://test2"));// 设置目录test2pb.command("cmd", "/c", "dir", ">>", "test1.log");// 执行命令,把结果输出到test1.logProcess process2 = pb.start();// 启动进程BufferedReader br2 = new BufferedReader(new InputStreamReader(process2.getInputStream(), "gbk"));String line2 = null;while ((line2 = br2.readLine()) != null) {//因为结果输出到了文件,所以本处无信息返回System.out.println(line2);}} catch (IOException e) {e.printStackTrace();throw e;}}
}
ProcessBuilder和Process的区别:
1、ProcessBuilder为进程提供了更多的控制,而Process的功能相对来说简单的多
2、ProcessBuilder是一个final类,有两个带参数的构造方法,你可以通过构造方法来直接创建ProcessBuilder的对象。而Process是一个抽象类,一般都通过Runtime.exec()和ProcessBuilder.start()来间接创建其实例。
ProcessBuilder的api:
内部类
方法 | 描述 |
---|---|
static class ProcessBuilder.Redirect
|
表示子进程的输入源或者输出的目的 |
构造器
方法 | 描述 |
---|---|
ProcessBuilder (String... command)
|
使用操作系统程序 和参数创建一个进程生成器 |
ProcessBuilder (List<String> command)
|
使用操作系统程序和参数创建一个进程生成器 |
方法
取出或设置程序和参数的方法
方法 | 描述 |
---|---|
List<String> command()
|
返回操作系统程序和该程序的参数。 |
ProcessBuilder command(List<String> command)
|
设置这个进程生成器的 操作系统程序 和 参数。 |
ProcessBuilder command(String... command)
|
置这个进程生成器的 操作系统程序 和 参数。 |
取出或设置工作目录的方法
方法 | 描述 |
---|---|
File directory()
|
返回此进程生成器的工作目录。 |
ProcessBuilder directory(File directory)
|
设置进程生成器的工作目录。 |
设置标准 IO 的方法
方法 | 描述 |
---|---|
ProcessBuilder redirectOutput(File file)
|
使用文件作为标准输出 |
ProcessBuilder redirectOutput(ProcessBuilder.Redirect destination)
|
使用 Redirect 对象作为标准输出
|
ProcessBuilder redirectInput(File file)
|
重定向标准输入到文件中 |
ProcessBuilder redirectInput(ProcessBuilder.Redirect source)
|
重定向标准输入 |
ProcessBuilder redirectError(File file)
|
将标出错误输出设置到文件中 |
ProcessBuilder redirectError(ProcessBuilder.Redirect destination)
|
设置标准错误输出的目标 |
取出标准 IO 的方法
方法 | 描述 |
---|---|
ProcessBuilder.Redirect redirectInput()
|
返回表示标准输入 的 Redirect 实例
|
ProcessBuilder.Redirect redirectError()
|
返回表示标准错误输出 的 Redirect 实例
|
ProcessBuilder.Redirect redirectOutput()
|
返回表示标出输出 的目标的 Redirect 实例
|
合并标准输出相关的方法
方法 | 描述 |
---|---|
ProcessBuilder inheritIO()
|
子进程和父进程使用相同的标准输入,标准输出,标准错误输出 |
ProcessBuilder redirectErrorStream(boolean redirectErrorStream)
|
设置 redirectErrorStream 属性
|
boolean redirectErrorStream()
|
判断进程生成器是否合并了标准错误输出和标准输出。 |
其他方法
方法 | 描述 |
---|---|
Map<String,String> environment()
|
返回保存进程生成器的环境变量的 Map 集合
|
启动进程方法
方法 | 描述 |
---|---|
Process start()
|
使用进程生成器中设置的属性启动新一个新的进程 |
Process 类 API 整理
杀死子进程
方法 | 描述 |
---|---|
abstract void destroy()
|
杀死子流程 |
Process destroyForcibly()
|
杀死子流程 |
获取子进程的 IO
方法 | 描述 |
---|---|
abstract InputStream getErrorStream()
|
返回连接到子进程的错误输出的输入流 |
abstract InputStream getInputStream()
|
返回连接到子进程的正常输出的输入流. |
abstract OutputStream getOutputStream()
|
返回连接到子进程的正常输入的输出流 |
其他方法
方法 | 描述 |
---|---|
abstract int exitValue()
|
返回子进程的退出值 |
boolean isAlive()
|
测试子流程是否有效 |
等待子进程
方法 | 描述 |
---|---|
abstract int waitFor()
|
使当前线程等待 Process 对象表示的进程终止
|
boolean waitFor(long timeout, TimeUnit unit)
|
使当前线程在必要时等待,直到此 Process 对象代表的子进程终止或经过指定的等待时间为止。
|
以上内容均来自网上参考整理。
Java执行系统命令策略相关推荐
- java怎么用doss窗口,java执行cmd命令
Java调用系统命令或可执... 3页 免费 喜欢此文档的还喜欢 Java远程方法调用 44页 1下载券 JAVA模块间调用 27页 2下载券 java调用CMD命令方法详解... ...... Wi ...
- java解决策略膨胀_折腾Java设计模式之策略模式
简介 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式.简单理解就是一组算法,可以互换,再简单点策略就是封装算法. 意图 定义一 ...
- java 执行外部命令 苹果_Java中执行外部命令
在项目中执行一个linux的shell脚本,于是需要在java环境下执行外部命令如系统命令.linux命令的需求,本人小小研究了一下,又上网查了一些资料先整理如下. java执行外部命令主要依赖两个类 ...
- Java中的策略设计模式
策略设计模式是一种行为模式,其中我们有多种算法/策略来完成一项任务,所使用的算法/策略留给客户选择. 各种算法选项封装在单独的类中. 在本教程中,我们将学习在Java中实现策略设计模式. UML表示形 ...
- Java状态和策略设计模式之间的差异
为了在Core Java应用程序中正确使用状态和策略设计模式,对于Java开发人员清楚地了解它们之间的区别很重要. 尽管状态和策略设计模式的结构相似,并且都基于开放式封闭设计原则,从SOLID设计原则 ...
- php java执行linux_java_java执行Linux命令的方法,本文实例讲述了java执行Linux命 - phpStudy...
java执行Linux命令的方法 本文实例讲述了java执行Linux命令的方法.分享给大家供大家参考.具体实现方法如下: public class StreamGobbler extends Thr ...
- Java常用设计模式-策略模式
策略模式是一个非常实用的设计模式,指定义了一类算法并将其封装起来,并使得它们之间可以灵活地切换,并且不影响客户端. 1,从一个例子开始 我们常常会在网上买东西,很多购物平台都会有着各种各样的优惠策略供 ...
- 什么是内存泄露?该怎么排查?Java内存泄漏策略
什么是内存泄漏 内存泄漏:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着. 在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的, ...
- Java Caching(缓存)-策略和JCache API
This Article Is From:https://dzone.com/refcardz/java-caching Written byAbhishek GuptaSenior Product ...
最新文章
- 【Java】 实现一副扑克牌,包含:洗牌+发牌(3个人,一人5张)+输出牌的信息 的逻辑
- jquery刷新iframe页面的方法(兼容主流)
- [Swift]LeetCode873. 最长的斐波那契子序列的长度 | Length of Longest Fibonacci Subsequence...
- Get SQL String From Query Object In Entity Framework
- markdown数学公式换行对齐_Markdown语法详细
- leetcode344. 反转字符串 史上最简单力扣题
- USB 3.0存储产品CeBIT集中展示
- (转)ATOM介绍和使用
- Linux文件目录类指令
- 第一类边界条件,三角单元剖分,线性插值的位场延拓,LDLT高效求解
- spark java jar 依赖_spark提交依赖jar包的解决方法
- 关于政府房价调控的一个误区
- 图像匹配之归一化积相关灰度匹配
- 小美赛:模拟机舱病毒传播
- 八皇后算法带给我们的启示吧
- CyberArk被评为2021年Gartner特权访问管理魔力象限的领导者
- .计算机软件系统包括,计算机软件系统包括什么
- 这半年,蔡崇信、张勇、彭蕾、井贤栋是怎么扛住马云“绩效”考核的?
- springcloud(十一):服务网关 Spring Cloud GateWay 入门
- 天气选择页面html,CSS3 天气预报界面组件
热门文章
- .net学习---ADO
- bzoj3202:[Sdoi2013]项链
- 自己定义AlertDialog对话框布局
- smart模版学习笔记一
- 政府门户应该怎样建设?——解读中国政府网站绩效评估标准
- 加了定位后div不显示了_FANUC主轴定位(M19)后诊断参数445不显示怎么办?
- android申请多个运行时权限,Android 6.0(API 23) 运行时权限(二)之权限申请
- mysql 电商实战_电商项目测试实战(一)
- linux 64位 php memcached 扩展,LINUX系统安装PHP的memcached扩展
- 设计师灵感交流社区|给你的作品一个舞台