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;
}
};
};
}
Demo源码