天天看點

java 7z壓縮算法_在 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 函數