Java魔法堂:找外援的利器——Runtime.exec详解
一、前言
Java虽然五脏俱全但总有软肋,譬如获取CPU等硬件信息,当然我们可以通过JNI调用C/C++来获取,但对于对C/C++和Windows API不熟的码农是一系列复杂的学习和踩坑过程。那能不能通过简单一些、学习成本低一些的方式呢?答案是肯定的,在功能实现放在首位的情况下,借他山之石是最简洁有力的做法。而 Runtime.exec方法 就为我们打开这么的一条路了。
二、认识 java.lang.Runtime.exec方法
作用:用于调用外部程序,并重定向外部程序的标准输入、标准输出和标准错误到缓冲池。功能就是和windows的“运行”一样啦。

方法重载:
exec(String command) ,调用外部程序,入参command为外部可执行程序的启动路径或命令。
exec(String[] cmdArray) ,调用外部程序,入参cmdArray的元素将组合成为一条完整的外部可执行程序的启动路径或命令。
exec(String command, String[] envp) ,在调用外部程序之前设置系统环境变量,该变量仅供command入参使用,envp每个元素为一个系统环境变量,并且字符串格式为“环境变量名=环境变量值”。
exec(String command, String[] envp, File dir) , 除了设置系统环境变量外,还通过入参dir设置当前工作目录。
实例 —— 在当前目录执行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 == ? "成功" : "失败");
}
catch(Exception e){
e.printStackTrace();
}
执行代码后查看c:\dir.txt文件内容如如下:
驱动器 D 中的卷没有标签。
卷的序列号是 -B214 D:\test 的目录 // : <DIR> movies
// : , readme.txt
三、注意点
1. Runtime.exec() 不是cmd或shell环境,因此无法直接调用dir等命令。若要调用命令行下的命令,请参考第2节的实例。
2. 通过 Process实例.getInputStream() 和 Process实例.getErrorStream() 获取的输入流和错误信息流是缓冲池向当前Java程序提供的,而不是直接获取外部程序的标准输出流和标准错误流。

而缓冲池的容量是一定的,因此若外部程序在运行过程中不断向缓冲池输出内容,当缓冲池填满,那么外部程序将暂停运行直到缓冲池有空位可接收外部程序的输出内容为止。(采用xcopy命令复制大量文件时将会出现该问题)
解决办法就是当前的Java程序不断读取缓冲池的内容,从而为腾出缓冲池的空间。
四、绝对是坑
为解决第3节第2点注意事项中提及的问题。我们可以通过下列两种方式处理
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 == ? "成功" : "失败");
}
catch(Exception e){
e.printStackTrace();
}
这里要注意一个坑:外部程序在执行结束后将会自动关闭,否则不管是字符流还是字节流均由于既读不到数据,又读不到流结束符而出现阻塞Java进程运行的情况。
而 cmd /c 就是告诉cmd环境进程,当执行完成后关闭自身。
五、总结
用适当的工具做适当的事, Runtime.exec方法 让我们功能实现的手段更灵活了!
尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/4081445.html ^_^肥仔John
六、参考
http://fuliang.iteye.com/blog/574260
Java魔法堂:找外援的利器——Runtime.exec详解的更多相关文章
- JS魔法堂:IMG元素加载行为详解
一.前言 在<JS魔法堂:jsDeferred源码剖析>中我们了解到img元素加载失败可以作为函数异步执行的优化方案,本文打算对img元素的加载行为进行更深入的探讨. 二.资源加载的相关属 ...
- java打开本地应用程序(调用cmd)---Runtime用法详解
有时候我们需要借助java程序打开电脑自带的一些程序,可以直接打开或者借助cmd命令窗口打开一些常用的应用程序或者脚本,在cmd窗口执行的命令都可以通过这种方式运行. 例如: package cn.x ...
- Java魔法堂:类加载器入了个门
一.前言 <Java魔法堂:类加载机制入了个门>中提及整个类加载流程中只有加载阶段作为码农的我们可以入手干预,其余均由JVM处理.本文将记录加载阶段的核心组件——类加载器的相关信息,以便日 ...
- Java魔法堂:打包知识点之jar
一.前言 通过eclipse导出jar包十分方便快捷,但作为码农岂能满足GUI的便捷呢?所以一起来CLI吧! 二.JAR包 JAR包是基于ZIP文件格式,用于将多个.java文件和各种资源文件, ...
- 【转】Java魔法堂:String.format详解
Java魔法堂:String.format详解 目录 一.前言 二.重载方法 三.占位符 四.对字符.字符串进行格式化 五.对整数进行格式化 六. ...
- Java开发利器Myeclipse全面详解
Java开发利器Myeclipse全面详解: Ctrl+1:修改代码错误 Alt+Shift+S:Source命令 Ctrl+7:单行注释 Ctrl+Shift+/ :多行注释 Ctrl+I :缩进( ...
- 史上!最最最简洁明了的 Java JDK 安装目录及其子目录含义 10分钟详解 - 精简归纳
Java JDK 安装目录及其子目录含义 10分钟详解 - 精简归纳 JERRY_Z. ~ 2020 / 8 / 30 转载请注明出处!️ 目录 Java JDK 安装目录及其子目录含义 10分钟详解 ...
- 深入浅出 Java JDK 安装目录及其子目录含义 10分钟详解 - 精简归纳
Java JDK 安装目录及其子目录含义 10分钟详解 - 精简归纳 JERRY_Z. ~ 2020 / 8 / 30 转载请注明出处!️ 目录 Java JDK 安装目录及其子目录含义 10分钟详解 ...
- (转)java之Spring(IOC)注解装配Bean详解
java之Spring(IOC)注解装配Bean详解 在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...
随机推荐
- php取默认值以及类的继承
(1)对于php的默认值的使用和C++有点类似,都是在函数的输入中填写默认值,以下是php方法中对于默认值的应用: <?phpfunction makecoffee($types = array ...
- 【背景建模】PbModel
PbModel是基于概率模型的背景差分算法,其基本思想是像素点会因光照变化.运动物体经过产生多种颜色值,但是一段时间内,像素点处于静止状态的时间会比处于运动状态的时间长.因而一段时间内,像素点某个颜色 ...
- 我们为什么要配置CATALINA_HOME环境变量
用文本编辑工具打开用于启动Tomcat的批处理文件startup.bat,仔细阅读.在这个文件中,首先判断CATALINA_HOME环境变量是否为空,如果为空,就将当前目录设为CATALINA_HOM ...
- (1)RGB-D SLAM系列- 工具篇(硬件+关键技术)
/*************************************************************************************************** ...
- 用css 制作三角
html代码: <div class="div"></div> css代码: .div{ border-top:40px solid #ff0077; bo ...
- 【iScroll源码学习03】iScroll事件机制与滚动条的实现
前言 想不到又到周末了,周末的时间要抓紧学习才行,前几天我们学习了iScroll几点基础知识: 1. [iScroll源码学习02]分解iScroll三个核心事件点 2. [iScroll源码学习01 ...
- 深入理解:JavaScript原型与继承
深入理解:JavaScript原型与继承 看过不少书籍,不少文章,对于原型与继承的说明基本上让人不明觉厉,特别是对于习惯了面向对象编程的人来说更难理解,这里我就给大家说说我的理解. 首先JavaScr ...
- JavaScript学习笔记-JSON对象
JSON 是一种用来序列化对象.数组.数值.字符串.布尔值和 null 的语法.它基于 JavaScript 语法,但是又有区别:一些 JavaScript 值不是 JSON,而某些 JSON 不是 ...
- Android基础面试题
1. 请描述一下Activity 生命周期. 答: 如下图所示.共有七个周期函数,按顺序分别是: onCreate(), onStart(), onRestart(), onResume(), onP ...
- C C++ TDD单元测试非常好的书
http://product.china-pub.com/199003 测试驱动的嵌入式C语言开发 Test Driven Development for Embedded C <测试驱动的嵌入 ...