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文件了,下面就看看 ...
随机推荐
- Guava学习笔记:Guava新增集合类型-Bimap
BiMap提供了一种新的集合类型,它提供了key和value的双向关联的数据结构. 通常情况下,我们在使用Java的Map时,往往是通过key来查找value的,但是如果出现下面一种场景的情况,我们就 ...
- jQuery Filterizr 筛选过滤
Filterizr 是一款功能强大的筛选过滤插件,它提供了多重筛选过滤方式,配合了css3的动画效果. 在线实例 默认 回调函数 使用方法 <div class="sucaihuo&q ...
- 使用 WordPress 插件模板开发高质量插件
WordPress 插件样板是标准化的,有组织的,面向对象的基础,用于构建高品质的 WordPress 插件.样板遵循编码标准和文件标准,所以你不必自己学习这些,根据注释编写代码即可. 官方网站 ...
- 发测试 HTML/FILE/MYSQL/动态 20151120
NilCMS几种页面输出方式: 1.直接生成html.不进行php处理. 2.生成文件缓存.针对于URL中单个目录文件过多,不利于管理.只进行PHP处理,不连接mysql. 3.生成mysql缓存.数 ...
- [Java] Tomcat环境变量设置
@echo off title Tomcat环境变量设置 color 0a set /p inputTH=D:\Work\024_Tomcat if /i "%inputTH%"= ...
- React Native学习笔记之1
1:运行React Native报连接错误解决 解决方式: 在终端进入项目文件里,然后执行:(cd Pods/React; npm run start) 2:组件生命周期介绍 创建阶段 1. getD ...
- 【代码笔记】iOS-点击任何处,出现城市
一,效果图. 二,工程目录. 三,代码. //点击任何处,出现城市 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { ...
- iOS 学习 - 13.微信分享链接、QQ 分享图片
准备工作---原文来自这个 首先要在微信开放平台申请 AppID 和 QQ ID(我第一天晚上申请的,第二天中午就通过了),接着导入 SDK,也就是3个 .h 和一个 .a 文件,详情见这里 如果你是 ...
- Sumlime Text编辑文件后快速刷新浏览器
作为Web开发人员,我们经常会这么做:在编辑器中调整代码,保存文件,切换到浏览器,然后刷新浏览器页面来查看结果.在代码编辑过程中,我们需要重复进行很多次这些操作. 如果你使用的是Sublime Tex ...
- callback的实现
Callback.h 继承层次 CallBack实现类 基类 第一层子类 第二层子类 第三层子类 SimpleRefCount CallbackImplBase CallbackImpl Functo ...