android zip4j之--解壓zip文件並實時顯示解壓進度

  Zip文件是我們經常用到壓縮文件格式,android中在進行網絡請求大批量數據時,通常會採用傳遞zip文件,這樣做即可以減少網絡流量的消耗,加快請求的響應速度,又可以減少對存儲空間的要求,所以當我們將zip文件讀取回來的時候,如何解壓就是一個要解決的問題,雖然java本身提供了zip相關的API,但不是很強大,所以我們採用apache開源組織的zip4j,通過這個jar包可以十分輕鬆的解壓zip文件.

   回到項目中去,項目中有個需求是從服務器請求雜誌,請求回來後給讀者展示,但是由於公司自己做的電子雜誌太大,最少也得20M,這是一個十分龐大的數據,所以與服務器商定採用zip來傳輸,可以降低文件的大小,減少服務器的壓力.我當時的處理過程:

    1.使用HttpURLConnection與服務器取得連接,得到輸入流inputstream.

    2.利用java zip流,將 inputstream轉化爲zip流.

    3.記錄每次傳輸的位置,保存於臨時文件中.(用於斷點續傳,由於數據量大,所以要做斷點續傳,以後詳解)

    4.循環讀取流完畢後生成一個zip文件,將zip文件解壓並實時將解壓進度顯示.

通過以上四步就完成了從服務器讀取zip包,並將zip包解壓給用戶展示,本文主要總結最後一步:

  

   通過閱讀zip4j官網demo,可以得知,這個jar包本身是支持對解壓進度的讀取這一功能的.下面是我自己寫的一個demo,可以實時的將解壓進度發送出來,在界面上進行更新.

先看一下demo的解壓進度效果圖,比較簡單,有了數據後,效果想做的多複雜都可以,例如可以根據進度去繪製一個進度條等.

   這是某一時刻的截圖.

代碼:      

package util;
import java.io.File;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.progress.ProgressMonitor;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
/**
 * @author rzq
 * @function  封裝一個解壓工具類,以後如果需要壓縮相關的方法,都放到此類中
 */
public class ZipUtil
{
	private static final String password = "test123";

	public static void unZipFileWithProgress(final File zipFile, final String filePath, final Handler handler,
			final boolean isDeleteZip) throws ZipException
	{
		ZipFile zFile = new ZipFile(zipFile);
		zFile.setFileNameCharset("GBK");

		if (!zFile.isValidZipFile())
		{ //
			throw new ZipException("exception!");
		}
		File destDir = new File(filePath); // ��ѹĿ¼
		if (destDir.isDirectory() && !destDir.exists())
		{
			destDir.mkdir();
		}
		if (zFile.isEncrypted())
		{
			zFile.setPassword(password); // 設置解壓密碼
		}

		final ProgressMonitor progressMonitor = zFile.getProgressMonitor();
		Thread thread = new Thread(new Runnable()
		{
			@Override
			public void run()
			{
				Bundle bundle = null;
				Message msg = null;
				try
				{
					int precentDone = 0;
					if (handler == null)
					{
						return;
					}
					handler.sendEmptyMessage(CompressStatus.START);
					while (true)
					{
						// 每隔50ms,發送一個解壓進度出去
						Thread.sleep(50);
						precentDone = progressMonitor.getPercentDone();
						bundle = new Bundle();
						bundle.putInt(CompressStatus.PERCENT, precentDone);
						msg = new Message();
						msg.what = CompressStatus.HANDLING;
						msg.setData(bundle);
						handler.sendMessage(msg); //通過 Handler將進度扔出去
						if (precentDone >= 100)
						{
							break;
						}
					}
					handler.sendEmptyMessage(CompressStatus.COMPLETED);
				}
				catch (InterruptedException e)
				{
					bundle = new Bundle();
					bundle.putString(CompressStatus.ERROR_COM, e.getMessage());
					msg = new Message();
					msg.what = CompressStatus.ERROR;
					msg.setData(bundle);
					handler.sendMessage(msg);
					e.printStackTrace();
				}
				finally
				{
					if (isDeleteZip)
					{
						zipFile.delete();//將原壓縮文件刪除
					}
				}
			}
		});
		thread.start();
		zFile.setRunInThread(true); //true 在子線程中進行解壓 , false主線程中解壓
		zFile.extractAll(filePath); //將壓縮文件解壓到filePath中...
	}
}

 /**
  *  封裝不同的解壓狀態
  *
  **/
 public class CompressStatus
{
    public final static int START = 10000;
    public final static int HANDLING = 10001;
    public final static int COMPLETED = 10002;
    public final static int ERROR = 10003;

    public final static String PERCENT = "PERCENT";
    public final static String ERROR_COM = "ERROR";
}

package com.example.zipprogress;

import java.io.File;

import net.lingala.zip4j.exception.ZipException;
import util.CompressStatus;
import util.ZipUtil;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;


/**
 * @author rzq
 * @function 要更新的 UI
 */
public class MainActivity extends Activity {
    TextView tv;
    String zipFilePath;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.text_progress);
        zipFilePath = Environment.getExternalStorageDirectory().toString()
                + "/Desktop.zip";
        File zipFile = new File(zipFilePath);
        try {
            ZipUtil.unZipFileWithProgress(zipFile,
                    Environment.getExternalStorageDirectory() + "/myTest/",
                    handler, false);
        } catch (ZipException e) {
            e.printStackTrace();
        }

    }

    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case CompressStatus.START:
                tv.setText("start!");
                break;
            case CompressStatus.HANDLING:
                Bundle b = msg.getData();
                tv.setText(b.getInt(CompressStatus.PERCENT) + "%");
                break;
            case CompressStatus.COMPLETED:
                tv.setText("end!");
                break;
            case CompressStatus.ERROR:
                tv.setText("error");
                break;
            }
        };
    };

}

總結:  主要就是對API的掌握和通過Handler對消息的傳遞,由於zip4j的下載需要翻強,所以我將demo代碼和zip4j包的源碼和jar文件都上傳,有需要的可以直接下載.

 

Demo源碼

發佈了66 篇原創文章 · 獲贊 59 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章