Java 使用Runtime.getRuntime.exec 和 ProcessBuilder 调用外部命令

来源:互联网 发布:中文版音乐制作软件 编辑:程序博客网 时间:2024/05/16 17:53

这几天在做来到公司以来的第一个项目,一个可以生成statcvs report的web小工具

昨天一天纠结于调用外部命令后程序阻塞的问题,直到刚刚终于解决。

我要调用的外部指令是 cvs log 生成某个项目源码的cvs日志文件

一开始我用的是Runtime.getRuntime.exec(cmd)方法,

Process process = Runtime.getRuntime().exec("cmd");OutputStream os = process.getOutputStream();InputStream es = process.getErrorStream();runCommand(os,"cd " + projectPath + "\n");runCommand(os, "E:" + "\n");runCommand(os, "cvs log -d \"" + date1 + "<" + date2 + "\" > " + logFilePath + "\n");


但是使用这个方法调用指令总是会运行一会儿就阻塞住。

后来我又改用ProcessBuilder, 同样出现了阻塞的问题,我google了一下,发现问题在于:

都有自己的标准输入、标准输出、标准错误输出,对于某些 依赖于OS的进程,可能其输出缓冲区很小,如果不能及时的读出(标准输出、标注错误输出),将导致进程不能正常退出。

我的程序中有对标准输出做了处理,但是cvs log指令还有错误输出,于是我在处理标准输出前新建一个线程读取错误输出缓冲区:

Process process = builder.start();InputStream is = process.getInputStream();InputStream es = process.getErrorStream();ErrorOutputReader errReader = new ErrorOutputReader(es);errReader.start();byte[] re=new byte[128];while (is.read(re)!=-1) {String temp = new String(re, 0, len(re),"UTF-8");System.out.println(temp);result = result+ temp;}
这样之后程序正常结束了,但让人恼火的是ProcessBuilder 不支持输出重定向指令,而我用上面的方法,即读取字节码再转为string存入文件生成的log文件却不准确,导致statcvs无法解析。


绝望之际我又转投支持重定向指令Runtime.getRuntime.exec(cmd),它能够准确生成log文件,而且也不用去care 标准输出的问题,我只要将错误输出缓冲区读完就行,

但是奇怪的是程序依旧阻塞,我百思不得其解,  纠结了一天始终卡在那里, 我想我脑袋都阻塞了。

后来我想 难道是标准输入的问题, 于是我加入了一句process.getOutoutStream().close(), 居然就神奇地不阻塞了。


这是什么原因?  莫非这个close()功能类似于命令行里输入ctrl+z?


总之问题就这样解决了。  好交差去喽!!!







Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

原创粉丝点击