在Java中执行系统命令,主要是使用ProcessBuilder和Runtime.getRuntime().exec()。而在这里主要是介绍两种方法的使用。

使用情景是在linux系统中,使用mencoder来进行视频转码。将视频转为flv格式,因为转为flv格式命令较为简单,如要转为MP4格式,可以看官方文档介绍

一.使用Runtime

##上传之后的视频文件名为test.tmpmedia
String command = "mencoder test.tmpmedia -o test.flv -ofps 25 -of lavf -oac mp3lame -srate 22050 -ovc lavc -lavcopts "
+ "vcodec=flv:keyint=59:vbitrate=6000:mbd=2:trell:v4mv:o=mpv_flagg=cbp_rd:last_pred=3 -vf harddup,scale=480:256"; Process p = Runtime.getRuntime().exec(command); ##读取命令的输出信息
InputStream is = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
p.waitFor();
if (p.exitValue() != 0) {
//说明命令执行失败
//可以进入到错误处理步骤中
} ##打印输出信息
String s = null;
while ((s = reader.readLine()) != null) {
System.out.println(s);
}

其中waitFor()方法会阻塞当前进程,直到命令执行结束。而exitValue不会阻塞进程,但是调用exitValue的时候,如果命令没有执行完成就会报错,感觉这样设计挺奇怪的。

所以,想要获取到命令是否执行成功,就搭配waitForexitValue

使用Runtime执行命令感觉是比较方便的,直接可以将命令写入exec()中。如果仅仅是这样写的话,转码是会一直卡死在那里的。而你将命令直接放到终端中执行,又不会出现问题。

原因就在转码时候,会输出大量的信息(标准输出和标准错误),如果不清理java的缓存区,就会导致缓存区满而命令无法继续执行的情况。

那么解决办法肯定就是清理缓存区,而使用Runtime清理的话,你至少得再开另外一个线程,才能同时getInputStreamgetErrorStream,这样并不是我喜欢的,所以便采用了ProcessBuilder

二.使用ProcessBuilder

#将命令分解为List存储
String[] commandSplit = command.split(" ");
List<String> lcommand = new ArrayList<String>();
for (int i = 0; i < commandSplit.length; i++) {
lcommand.add(commandSplit[i]);
} ProcessBuilder processBuilder = new ProcessBuilder(lcommand);
processBuilder.redirectErrorStream(true);
Process p = processBuilder.start();
InputStream is = p.getInputStream();
BufferedReader bs = new BufferedReader(new InputStreamReader(is)); p.waitFor();
if (p.exitValue() != 0) {
//说明命令执行失败
//可以进入到错误处理步骤中
}
String line = null;
while ((line = bs.readLine()) != null) {
System.out.println(line);
resultLog += line;
}

ProcessBuilder可以使用redirectErrorStream将标准输出和标准错误流合并,然后使用getInputStream获取到流,放入BufferedReader中打印出来,便可解决缓存区满的问题

唯一感觉不太方便就是命令执行已List<String>或者String []的形式传入。

上面的两种方法都是以阻塞的方式执行命令的,要想在后台执行命令,并且命令执行成功后通知,失败后记录日志,那就只能在主线程中开一个线程,专门用来转码。可以参考下一篇文章《

Spring中多线程转码,bean的注入问题》

Java 执行系统命令的更多相关文章

  1. Java 执行系统命令工具类(commons-exec)

    依赖jar <!-- 可以在JVM中可靠地执行外部进程的库. --> <dependency> <groupId>org.apache.commons</gr ...

  2. Java执行系统命令工具类(JDK自带功能)

    CommandUtil.java package utils; import java.io.ByteArrayOutputStream; import java.io.IOException; im ...

  3. java执行系统命令, 返回执行结果

    package com.geostar.gfstack.opinion.util; import java.io.BufferedReader; import java.io.Closeable; i ...

  4. java中执行系统命令

    java程序中执行系统命令猛击下面的链接看看你就知道怎么用了 http://blog.csdn.net/a19881029/article/details/8063758 http://wuhongy ...

  5. 在Loadrunner中如何用system函数执行系统命令

    前提: windows 系统 实现功能:用 LR 中的system函数执行系统命令 相关功能:在LR中利用C函数建立文件,写文件,读文件. 主要相关函数:sprintf/fopen/fgetc/fre ...

  6. Oracle数据库提权(dba权限执行系统命令)

    0x01 提权准备 这里我们先创建一个低权限的用户test SQL> conn sys/admin123@orcl as sysdba; 已连接. SQL> create user tes ...

  7. java 执行shell命令及日志收集避坑指南

    有时候我们需要调用系统命令执行一些东西,可能是为了方便,也可能是没有办法必须要调用.涉及执行系统命令的东西,则就不能做跨平台了,这和java语言的初衷是相背的. 废话不多说,java如何执行shell ...

  8. Java执行Dos-Shell脚本

    Java执行Dos-Shell脚本 1.介绍 2.调用shell脚本 2.1 获取键盘输入 2.2 构建指令 2.3 Java代码 3.Java调用Shell并传入参数 4.Java调用远程的Shel ...

  9. java 执行 jar 包中的 main 方法

    java 执行 jar 包中的 main 方法 通过 OneJar 或 Maven 打包后 jar 文件,用命令: java -jar ****.jar执行后总是运行指定的主方法,如果 jar 中有多 ...

随机推荐

  1. msql,触发器无事物回滚,插入之前满足条件再插入

    很少写mysql的触发器和存储过程,由于需要需要做一个很小的判断,要用到触发器,要达到的效果就是,插入之前判断是否满足条件如果不满足就不插入 如果用sqlserver 或者orcale 就很简单,按s ...

  2. Swift设置textView的行间距

    let textview = UITextView(frame: CGRect(x: 100, y: 100, width: 100, height: 200)) let paraph = NSMut ...

  3. CAS示例环境部署及配置

    http://wenku.baidu.com/link?url=d6JjWqOtuUediSkV18XagtVG9lVC2hTiaIEimfIgv1PIW8RMA1sXeIqqtJkW90lleYPQ ...

  4. nodejs学习笔记二:解析express框架项目文件

    上一章介绍了如何去创建一个express框架的工程项目,这章介绍一下express框架下的文件和用法解析,上一张我们创建的工程项目结构图如下: models是不属于原工程项目结构,为了实现数据模型后添 ...

  5. web项目开发规范整理总结

    一.类.函数.变量名命名: 1.定义类时,全部拼音的首字母必须大写:如Person,ClassDemo:(帕斯卡命名法):也可以用带下斜杆的匈牙利命名法进行命名,如    head_navigatio ...

  6. CSS3样式

    1.边框 div{border:2px solid;border-radius:25px;-moz-border-radius:25px; /* Old Firefox */} border-radi ...

  7. tomcat作为服务器的配置

    tomcat在启动时,会读取环境变量的信息,需要一个CATALINA_HOME 与JAVA_HOME的信息,CATALINA_HOME即tomcat的主目录,JAVA_HOME即java安装的主目录, ...

  8. shell导出mysql部分数据

    #!/bin/shSYSTEM=`uname -s` echo "echo"$SYSTEM if [[ $SYSTEM = "Linux" ]]; then   ...

  9. 使用日期控件datePicker,阻止移动端的自动调取键盘的事件

    方法:简单来说就是阻止input的默认事件. 因为datePicker就是用input来封装的,所以直接阻止input的输入事件就ok: 很简单,把input field属性readonly设置为tr ...

  10. 一看便知linux下mysql报错ERROR 1044: Access denied for user: '@localhost' to database 'mysql'

    错误信息:ERROR 1044: Access denied for user: '@localhost' to database 'mysql' linux下解决方案: mysql> use ...