zip文件的解壓可以使用java的zip庫,但是沒有實現對加密文件的解壓功能,這裡可以使用zip4j來實現。具體可以參看該文《Android下zip壓縮文件加密解密的完美解決方案 http://www.linuxidc.com/Linux/2014-11/109061.htm 》。該文件中沒有實現解壓進度的功能,這裡進行一簡單的實現。
Zip4jSp.java
/**
* unzip file to dest dir with password in thread.
*
* @param zipFile
* @param dest
* @param passwd
* @param charset
* null or empty is utf-8
* @param Handler
* handler in thread
* @param isDeleteZipFile
* true:delete zip file.false:not.
* @throws ZipException
*/
public static void Unzip(final File zipFile, String dest, String passwd,
String charset, final Handler handler, final boolean isDeleteZipFile)
throws ZipException {
ZipFile zFile = new ZipFile(zipFile);
if (TextUtils.isEmpty(charset)) {
charset = "UTF-8";
}
zFile.setFileNameCharset(charset);
if (!zFile.isValidZipFile()) {
throw new ZipException(
"Compressed files are not illegal, may be damaged.");
}
File destDir = new File(dest); // Unzip directory
if (destDir.isDirectory() && !destDir.exists()) {
destDir.mkdir();
}
if (zFile.isEncrypted()) {
zFile.setPassword(passwd.toCharArray());
}
final ProgressMonitor progressMonitor = zFile.getProgressMonitor();
Thread progressThread = new Thread(new Runnable() {
@Override
public void run() {
Bundle bundle = null;
Message msg = null;
try {
int percentDone = 0;
// long workCompleted=0;
// handler.sendEmptyMessage(ProgressMonitor.RESULT_SUCCESS)
if (handler == null) {
return;
}
handler.sendEmptyMessage(CompressStatus.START);
while (true) {
Thread.sleep(1000);
percentDone = progressMonitor.getPercentDone();
bundle = new Bundle();
bundle.putInt(CompressKeys.PERCENT, percentDone);
msg = new Message();
msg.what = CompressStatus.HANDLING;
msg.setData(bundle);
handler.sendMessage(msg);
if (percentDone >= 100) {
break;
}
}
handler.sendEmptyMessage(CompressStatus.COMPLETED);
} catch (InterruptedException e) {
bundle = new Bundle();
bundle.putString(CompressKeys.ERROR, e.getMessage());
msg = new Message();
msg.what = CompressStatus.ERROR;
msg.setData(bundle);
handler.sendMessage(msg);
e.printStackTrace();
}
finally
{
if(isDeleteZipFile)
{
zipFile.deleteOnExit();//zipFile.delete();
}
}
}
});
progressThread.start();
zFile.setRunInThread(true);
zFile.extractAll(dest);
}
注:
(1)、字符集默認采用UTF-8
(2)、解壓文件在線程中進行,所以需要setRunInThread(true).由於采用線程中解壓文件,所以調用該函數時相當於異步執行,調用代碼會直接往下走,需要注意並加以處理。
(3)、進度條另開了一個線程來處理,並將處理的結果以handler的形式發送
(4)、使用zipFile.deleteOnExit()而不是zipFile.delete();因為使用線程解壓時,雖然從progressMonitor獲得的percentDone已經達到了100,而事實上數據並沒有完全解壓完成。這時退出循環執行finally的delete函數,如果使用zipFile.delete(),將會刪除文件,這樣會使後續的解壓失敗。而使用zipFile.deleteOnExit()函數,該函數是當VM終止時才會刪除文件,與zipFile.delete()刪除文件不同。APP在運行時,VM始終是在的,所以這樣刪除可以確保後續的解壓能夠正常進行。或者不去刪除文件。
(5)、handler的代碼見後文的MainActivity.java。
CompressKeys.java
package com.sparkle.compress;
public class CompressKeys {
public final static String PERCENT="PERCENT";
public final static String ERROR="ERROR";
}
CompressStatus.java
package com.sparkle.compress;
public class CompressStatus {
public final static int START=0;
public final static int HANDLING=1;
public final static int COMPLETED=2;
public final static int ERROR=3;
}
MainActivity.java
private Handler _handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CompressStatus.START:
{
setTitle("Start...");
break;
}
case CompressStatus.HANDLING:
{
Bundle bundle=msg.getData();
int percent=bundle.getInt(CompressKeys.PERCENT);
setTitle(percent+"%");
break;
}
case CompressStatus.ERROR:
{
Bundle bundle=msg.getData();
String error=bundle.getString(CompressKeys.ERROR);
_info_textView.setText(error);
break;
}
case CompressStatus.COMPLETED:
{
setTitle("Completed");
byte[] data=FileSp.read(tempFilePath);
try {
String dataStr=new String(data,"UTF-8");
_info_textView.setText(dataStr);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
default:
break;
}
};
};
}
下面是效果圖
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11