小弟菜鸟,现在在给客户做一个java程序调用winRAR命令行,生成一个压缩包,供用户下载的功能。现在这个功能倒是完成了,但是有个问题,那就是如果需要添加进压缩包的附件比较大,比如说超过了5M,则winrar程序一直在运行,不能正常退出,导致java主程序一直被挂起,用户打包下载rar压缩包失败。
代码如下:
[code="java"]
/**
* 每次只是添加一个文件进压缩包,这样做没出现过问题
* @param RARCMD winrar进行压缩的命令行,格式为 D:\Program Files\WinRAR\Rar.exe a -ep
* @param fileName 需要压缩的文件名(必须包含路径) ,如果该参数为null或者为空字符串,则直接返回,不做任何事
* @param RARRealpath 压缩后的压缩文件存放路径,包含文件名
* @throws Exception
*/
public static void RARFile(String RARCMD, String fileName, String RARRealpath) throws Exception {
if (fileName == null) {
return;
}
fileName = fileName.trim();
if (fileName.equals("")) {
return;
}
String exec = RARCMD + " " + RARRealpath + " " + fileName;
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(exec);
// 当前线程等待该process结束,既挂起主线程
p.waitFor();
}
[/code]
如果我这么调用:
[code="java"]
RARFile("D:\Program Files\WinRAR\Rar.exe a -ep", "d:\字符串2", "d:\download.rar");
[/code]
其中待添加进压缩包“d:\download.rar”的文件"d:\字符串2",如果文件"d:\字符串2",超过5M(没有精确测试多大,但是超过5M肯定就不行了),那么,程序执行到
[code="java"]p.waitFor();[/code]
就不动弹了,打开任务管理器,可以看到Rar.exe一直在运行,不会自行结束。这样的话,java当前的线程一直被挂起,导致用户下载rar压缩包失败。
但是相同的winRAR命令行,比如说:
[code="java"]
D:\Program Files\WinRAR\Rar.exe a -ep d:\download.rar d:\字符串2
[/code]
在cmd下执行,却任何问题没有,不用几秒就压缩完毕,打开任务管理器,Rar.exe也正常退出,在D盘根目录下,也正确的生成了“download.rar”压缩包。
现在的问题就是,在cmd下执行rar命令行,和在java里执行相同的命令行,Rar.exe有不同的反应,如果需要压缩的文件比较大(超过5M),则在java里就不行。请教各位高手,这个问题应该怎么解决?
对了,winRAR的版本是3.92
小文件一下就压缩完成了, 所以可以, 但是文件大了, winrar会输出压缩的百分比信息, 需要将这些信息读取出来, 否则输出流阻塞了, winrar处于等待状态...
[code="java"]public static void RARFile(String RARCMD, String fileName, String RARRealpath) throws Exception {
if (fileName == null) {
return;
}
fileName = fileName.trim();
if (fileName.equals("")) {
return;
}
String exec = RARCMD + " " + RARRealpath + " " + fileName;
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(exec);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), "gbk"));
String line;
while ((line = br.readLine()) != null) {
//System.out.println(line);
}
br = new BufferedReader(new InputStreamReader(p.getErrorStream(), "gbk"));
while ((line = br.readLine()) != null) {
//System.err.println(line);
}
// 当前线程等待该process结束,既挂起主线程
p.waitFor();
}[/code]
这个是由于进程的输出流阻塞的缘故导致的,需要老外开启线程清除Process的输出流和错误流才可以的。不过自己写还是比较麻烦的,建议使用apache的exec项目,可以非常方便的调用程序执行。
项目地址:[url]http://commons.apache.org/exec/[/url]
使用也非常简单,如下:
[code="java"]
CommandLine cl = CommandLine.parse("D:\Program Files\WinRAR\Rar.exe a -ep d:\download.rar d:\字符串2");
Executor executor = new DefaultExecutor();
executor.execute(cl);
[/code]
更多的用法请参看官方的文档吧