android zip4j之--解压zip文件并实时显示解压进度

52 篇文章 0 订阅
5 篇文章 0 订阅

  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源码

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
要在MFC中解压ZIP文件显示进度,可以使用Windows API中的ZipArchive类和ZipFile类。以下是一个简单的示例代码,可以在MFC应用程序中使用: ```c++ #include <iostream> #include <fstream> #include <Windows.h> #include <zipapi.h> // 回调函数,用于显示解压进度 BOOL CALLBACK MyProgressCallback(ZIP_PROGRESS_CALLBACK_REASON reason, DWORD64 bytesProcessed, DWORD64 totalBytesToProcess, PVOID userData) { int progress = (int)(bytesProcessed * 100 / totalBytesToProcess); std::cout << "Unzipping: " << progress << "%" << std::endl; return TRUE; } void UnzipFile(LPCTSTR zipFileName, LPCTSTR destFolder) { // 创建ZipArchive对象 ZipArchive zipArchive; if (!zipArchive.Open(zipFileName)) { std::cout << "Failed to open zip file" << std::endl; return; } // 获取ZIP文件中的文件数量 int fileCount = zipArchive.GetFileCount(); // 遍历ZIP文件中的所有文件 for (int i = 0; i < fileCount; i++) { // 获取文件名和文件大小 CString fileName = zipArchive.GetFileName(i); DWORD fileSize = zipArchive.GetFileSize(i); // 创建ZipFile对象 ZipFile zipFile; if (!zipFile.Open(&zipArchive, i)) { std::cout << "Failed to open zip file for reading" << std::endl; continue; } // 创建目标文件 CString destFilePath = destFolder + fileName; std::ofstream destFile(destFilePath, std::ios::out | std::ios::binary); if (!destFile) { std::cout << "Failed to create destination file" << std::endl; continue; } // 解压文件显示进度 if (!zipFile.ExtractFile(&MyProgressCallback, NULL, &destFile)) { std::cout << "Failed to extract file: " << fileName << std::endl; continue; } std::cout << "Extracted file: " << fileName << std::endl; } } int main() { LPCTSTR zipFileName = L"C:\\test.zip"; LPCTSTR destFolder = L"C:\\test\\"; UnzipFile(zipFileName, destFolder); return 0; } ``` 在上面的示例代码中,我们首先通过ZipArchive类打开ZIP文件,然后遍历ZIP文件中的所有文件,并使用ZipFile类将文件解压到目标文件夹中。在解压过程中,我们使用回调函数MyProgressCallback来显示解压进度,该函数在解压每个文件之前都会被调用。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值