通过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执行系统命令策略相关推荐

  1. java怎么用doss窗口,java执行cmd命令

    Java调用系统命令或可执... 3页 免费 喜欢此文档的还喜欢 Java远程方法调用 44页 1下载券 JAVA模块间调用 27页 2下载券 java调用CMD命令方法详解... ...... Wi ...

  2. java解决策略膨胀_折腾Java设计模式之策略模式

    简介 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式.简单理解就是一组算法,可以互换,再简单点策略就是封装算法. 意图 定义一 ...

  3. java 执行外部命令 苹果_Java中执行外部命令

    在项目中执行一个linux的shell脚本,于是需要在java环境下执行外部命令如系统命令.linux命令的需求,本人小小研究了一下,又上网查了一些资料先整理如下. java执行外部命令主要依赖两个类 ...

  4. Java中的策略设计模式

    策略设计模式是一种行为模式,其中我们有多种算法/策略来完成一项任务,所使用的算法/策略留给客户选择. 各种算法选项封装在单独的类中. 在本教程中,我们将学习在Java中实现策略设计模式. UML表示形 ...

  5. Java状态和策略设计模式之间的差异

    为了在Core Java应用程序中正确使用状态和策略设计模式,对于Java开发人员清楚地了解它们之间的区别很重要. 尽管状态和策略设计模式的结构相似,并且都基于开放式封闭设计原则,从SOLID设计原则 ...

  6. php java执行linux_java_java执行Linux命令的方法,本文实例讲述了java执行Linux命 - phpStudy...

    java执行Linux命令的方法 本文实例讲述了java执行Linux命令的方法.分享给大家供大家参考.具体实现方法如下: public class StreamGobbler extends Thr ...

  7. Java常用设计模式-策略模式

    策略模式是一个非常实用的设计模式,指定义了一类算法并将其封装起来,并使得它们之间可以灵活地切换,并且不影响客户端. 1,从一个例子开始 我们常常会在网上买东西,很多购物平台都会有着各种各样的优惠策略供 ...

  8. 什么是内存泄露?该怎么排查?Java内存泄漏策略

    什么是内存泄漏 内存泄漏:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着. 在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的, ...

  9. Java Caching(缓存)-策略和JCache API

    This Article Is From:https://dzone.com/refcardz/java-caching Written byAbhishek GuptaSenior Product ...

最新文章

  1. 【Java】 实现一副扑克牌,包含:洗牌+发牌(3个人,一人5张)+输出牌的信息 的逻辑
  2. jquery刷新iframe页面的方法(兼容主流)
  3. [Swift]LeetCode873. 最长的斐波那契子序列的长度 | Length of Longest Fibonacci Subsequence...
  4. Get SQL String From Query Object In Entity Framework
  5. markdown数学公式换行对齐_Markdown语法详细
  6. leetcode344. 反转字符串 史上最简单力扣题
  7. USB 3.0存储产品CeBIT集中展示
  8. (转)ATOM介绍和使用
  9. Linux文件目录类指令
  10. 第一类边界条件,三角单元剖分,线性插值的位场延拓,LDLT高效求解
  11. spark java jar 依赖_spark提交依赖jar包的解决方法
  12. 关于政府房价调控的一个误区
  13. 图像匹配之归一化积相关灰度匹配
  14. 小美赛:模拟机舱病毒传播
  15. 八皇后算法带给我们的启示吧
  16. CyberArk被评为2021年Gartner特权访问管理魔力象限的领导者
  17. .计算机软件系统包括,计算机软件系统包括什么
  18. 这半年,蔡崇信、张勇、彭蕾、井贤栋是怎么扛住马云“绩效”考核的?
  19. springcloud(十一):服务网关 Spring Cloud GateWay 入门
  20. 天气选择页面html,CSS3 天气预报界面组件

热门文章

  1. .net学习---ADO
  2. bzoj3202:[Sdoi2013]项链
  3. 自己定义AlertDialog对话框布局
  4. smart模版学习笔记一
  5. 政府门户应该怎样建设?——解读中国政府网站绩效评估标准
  6. 加了定位后div不显示了_FANUC主轴定位(M19)后诊断参数445不显示怎么办?
  7. android申请多个运行时权限,Android 6.0(API 23) 运行时权限(二)之权限申请
  8. mysql 电商实战_电商项目测试实战(一)
  9. linux 64位 php memcached 扩展,LINUX系统安装PHP的memcached扩展
  10. 设计师灵感交流社区|给你的作品一个舞台