java xml压缩成7zip,在 Java 项目中解压7Zip特殊压缩算法文件

1 问题描述

Java Web 后端下载了一个经特殊算法压缩的 zip 文件,因为不能采用 java 本身自带的解压方式,必须采用 7Zip 来解压。所以,提到了本文中在 java web 后端调用外部 7zip exe 来解压文件的问题。

2 主要实现

2.1 定义缓冲区类

class StreamGobbler extends Thread {

InputStream is;

String type;

public StreamGobbler(InputStream is, String type) {

this.is = is;

this.type = type;

}

public void run() {

try {

InputStreamReader isr = new InputStreamReader(is);

BufferedReader br = new BufferedReader(isr);

String line=null;

while ((line = br.readLine()) != null) {

System.out.println(type + ">" + line);

}

} catch (IOException ioe){

ioe.printStackTrace();

}

}

}

2.2 执行外部 exe 流程

String[] cmd = {

"7za.exe",

"x",

zipPath,

"-o" + outputPath

};

Runtime rt = Runtime.getRuntime();

Process proc = rt.exec(cmd);

// 监听出错信息

StreamGobbler errorGobbler = new

StreamGobbler(proc.getErrorStream(), "ERROR");

// 监听输出信息

StreamGobbler outputGobbler = new

StreamGobbler(proc.getInputStream(), "OUTPUT");

// 启动监听输入

errorGobbler.start();

outputGobbler.start();

// 确保 Runtime.exec 进程执行完毕

int exitVal = proc.waitFor();

System.out.println("ExitValue: " + exitVal);

3 重点解决

3.1 Process.waitFor 在 tomcat 中执行时,卡死状态

3.1.1 问题原因

一定要在调用Process.waitFor()前将程序的stdout和stderr都读完,否则就有可能因为pipe的缓冲区不够,被调用的系统命令阻塞在标准输出和标准错误输出上。Windows因为这个缓冲区的默认值比较小更容易出现这个问题。

需要注意读取程序的stdout和stderr都是阻塞的操作,这意味着必须在两个线程里分别读取,而不是在一个线程里一次读取,否则还是有可能出现阻塞的情况。

[http://www.dongliu.net/post/496142]

3.1.2 其他猜测

1. 程序主进程会等待process一定的时间,但是时间很少,可能process根本无法完成工作就结束了。 因此,针对使用较长时间做工作的process,就需要调用waitFor方法。 该方法会引起当前Thread等待,直到process中断。 [http://ccchhhlll1988-163-com.iteye.com/blog/1901497]

2. 可能是因为在 tomcat 中启动了一个进程,但是没有权限来杀死这个进程,所以,一直卡在这个界面

4 其他

4.1 用 Java 自带的解压库

java.util.zip

由于算法不一致,解压时提示: “invalid CEN header(bad compression method)”

4.2 下载 7Zip 的解压库

在 sourceforge 网站下载 sevenzipjbinding 压缩包。而且下载的也不是打包好的压缩文件

但是由于不支持最新的解压算法取消。

4.3 tomcat 下是否有调用外部 exe 的权限

4.4 启动tomcat失败

服务器能够正常启动项目,但是本地电脑不能启动。提示信息: "org.apache.catalina.LifecycleException: Failed to start component"

当本地 tomcat6 测试调用外部 exe 成功之后,就考虑在实际项目中测试项目是否成功,实际项目中用的是 tomcat7,同时包含了相应的 jdk 文件夹,进行了一定的改装。比如:修改了存放 webapp 的文件夹路径等;删除了一些不必要的文件等;

发现最终原因是因为: 启动时使用了本地较低版本的 jdk,设置 JAVA_HOME 为打包自带的 jdk 文件夹即可。

5 参考资料

1. runtime.getruntime.exec 中 waitfor 的用法

程序设计时,有时候需要在等待调用的系统程序完成操作后,当前线程才能做下一步操作,此时可以用类Process的方法waitFor()来实现,它会阻塞当先线程直至调用程序运行结束。

2. 正确的调用系统命令——为Process.waitFor设置超时以及其他

所以在代码中加入超时控制是必须的。但是Process.waitFor()本身并不支持超时时间设置,

一个方法是改用非阻塞的Process.exitValue()方法,然后轮询检查进程状态,这种方式比较消耗CPU,以至于轮询间隔也不能设置得太小,总归不是很完美。

另外就是另起一个线程来调用程序,在主线程中发现超时的时候,直接调用process.destroy()终止进程。

3. When Runtime.exec() won‘t

介绍为什么不能正常执行 Runtime 函数

原文:http://blog.csdn.net/lvye1221/article/details/38662369

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值