zoukankan      html  css  js  c++  java
  • 在 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由于这个缓冲区的默认值比較小更easy出现这个问题。


    须要注意读取程序的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失败 


    server可以正常启动项目,可是本地电脑不能启动。提示信息: "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 函数



  • 相关阅读:
    数据库概念相关
    JavaWeb基础知识总结
    MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作
    MyBatis学习总结(一)——MyBatis快速入门
    [源码解析]HashMap和HashTable的区别(源码分析解读)
    MyBatis学习总结(三)——优化MyBatis配置文件中的配置
    MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突
    MyBatis学习总结(五)——实现关联表查询
    MyBatis学习总结(六)——调用存储过程
    MyBatis学习总结(七)——Mybatis缓存
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4330743.html
Copyright © 2011-2022 走看看