版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

Android 压缩解压zip文件一般分为两种方式:

  • 基于JDK的Zip压缩工具类

  该版本存在问题:压缩时如果目录或文件名含有中文,压缩后会变成乱码;

  使用Java的zip包可以进行简单的文件压缩和解压缩处理时,但是遇到包含中文汉字目录或者包含多层子目录的复杂目录结构时,容易出现各种各样的问题。

  • 基于Ant的Zip压缩工具类

  需要第三方JAR包:Apache的ant.jar;

  解决了上面存在的问题。

效果图

代码分析

常用的方法:

压缩文件:

makeZip(String[] srcFilePaths, String zipPath)

解压文件:

unZip(String zipFilePath, String targetDirPath)

使用步骤

一、项目组织结构图

注意事项:

1、  导入类文件后需要change包名以及重新import R文件路径

2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤

将相关jar包复制到项目的libs目录下并同步Gradle File

jar包下载地址:链接:http://pan.baidu.com/s/1c1DlLc8 密码:8aq7

将AntZipUtils文件复制到项目中

package com.why.project.antziputilsdemo.utils;

import android.util.Log;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipException;
/**
* @Create By HaiyuKing
* @Used 基于Ant的Zip压缩工具类
* @参考资料 http://yunzhu.iteye.com/blog/1480293
* http://www.cnblogs.com/wainiwann/archive/2013/07/17/3196196.html
* http://blog.csdn.net/growing_tree/article/details/46009813
* http://www.jb51.net/article/69773.htm
*/
public class AntZipUtils { public static final String ENCODING_DEFAULT = "UTF-8"; public static final int BUFFER_SIZE_DIFAULT = 1024; /**生成ZIP压缩包【建议异步执行】
* @param srcFilePaths - 要压缩的文件路径字符串数组【如果压缩一个文件夹,则只需要把文件夹目录放到一个数组中即可】
* @param zipPath - 生成的Zip路径*/
public static void makeZip(String[] srcFilePaths, String zipPath)throws Exception {
makeZip(srcFilePaths, zipPath, ENCODING_DEFAULT);
} /**生成ZIP压缩包【建议异步执行】
* @param srcFilePaths - 要压缩的文件路径字符串数组
* @param zipPath - 生成的Zip路径
* @param encoding - 编码格式*/
public static void makeZip(String[] srcFilePaths, String zipPath,String encoding) throws Exception {
File[] inFiles = new File[srcFilePaths.length];
for (int i = 0; i < srcFilePaths.length; i++) {
inFiles[i] = new File(srcFilePaths[i]);
}
makeZip(inFiles, zipPath, encoding);
} /**生成ZIP压缩包【建议异步执行】
* @param srcFiles - 要压缩的文件数组
* @param zipPath - 生成的Zip路径*/
public static void makeZip(File[] srcFiles, String zipPath) throws Exception {
makeZip(srcFiles, zipPath, ENCODING_DEFAULT);
} /**生成ZIP压缩包【建议异步执行】
* @param srcFiles - 要压缩的文件数组
* @param zipPath - 生成的Zip路径
* @param encoding - 编码格式*/
public static void makeZip(File[] srcFiles, String zipPath, String encoding)
throws Exception {
ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipPath)));
zipOut.setEncoding(encoding);
for (int i = 0; i < srcFiles.length; i++) {
File file = srcFiles[i];
doZipFile(zipOut, file, file.getParent());
}
zipOut.flush();
zipOut.close();
} private static void doZipFile(ZipOutputStream zipOut, File file, String dirPath) throws FileNotFoundException, IOException {
if (file.isFile()) {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
String zipName = file.getPath().substring(dirPath.length());
while (zipName.charAt(0) == '\\' || zipName.charAt(0) == '/') {
zipName = zipName.substring(1);
}
ZipEntry entry = new ZipEntry(zipName);
zipOut.putNextEntry(entry);
byte[] buff = new byte[BUFFER_SIZE_DIFAULT];
int size;
while ((size = bis.read(buff, 0, buff.length)) != -1) {
zipOut.write(buff, 0, size);
}
zipOut.closeEntry();
bis.close();
} else {
File[] subFiles = file.listFiles();
for (File subFile : subFiles) {
doZipFile(zipOut, subFile, dirPath);
}
}
} /**解压ZIP包【建议异步执行】
* @param zipFilePath ZIP包的路径
* @param targetDirPath 指定的解压缩文件夹地址 */
public static void unZip(String zipFilePath, String targetDirPath)throws IOException,Exception {
unZip(new File(zipFilePath), targetDirPath);
} /**解压ZIP包【建议异步执行】
* @param zipFile ZIP包的文件
* @param targetDirPath 指定的解压缩目录地址 */
public static void unZip(File zipFile, String targetDirPath) throws IOException,Exception {
//先删除,后添加
if (new File(targetDirPath).exists()) {
new File(targetDirPath).delete();
}
new File(targetDirPath).mkdirs(); ZipFile zip = new ZipFile(zipFile);
Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.getEntries();
while (entries.hasMoreElements()) {
ZipEntry zipEntry = entries.nextElement();
if (zipEntry.isDirectory()) {
// TODO
} else {
String zipEntryName = zipEntry.getName();
if(zipEntryName.contains("../")){//2016-08-25
throw new Exception("unsecurity zipfile");
}else{
if (zipEntryName.indexOf(File.separator) > 0) {
String zipEntryDir = zipEntryName.substring(0, zipEntryName.lastIndexOf(File.separator) + 1);
String unzipFileDir = targetDirPath + File.separator + zipEntryDir;
File unzipFileDirFile = new File(unzipFileDir);
if (!unzipFileDirFile.exists()) {
unzipFileDirFile.mkdirs();
}
} InputStream is = zip.getInputStream(zipEntry);
FileOutputStream fos = new FileOutputStream(new File(targetDirPath + File.separator + zipEntryName));
byte[] buff = new byte[BUFFER_SIZE_DIFAULT];
int size;
while ((size = is.read(buff)) > 0) {
fos.write(buff, 0, size);
}
fos.flush();
fos.close();
is.close();
}
}
}
} /**
* 使用Apache工具包解压缩zip文件 【使用Java的zip包可以进行简单的文件压缩和解压缩处理时,但是遇到包含中文汉字目录或者包含多层子目录的复杂目录结构时,容易出现各种各样的问题。】
* @param sourceFilePath 指定的解压缩文件地址
* @param targetDirPath 指定的解压缩目录地址
* @throws IOException
* @throws FileNotFoundException
* @throws ZipException
*/
public static void uncompressFile(String sourceFilePath, String targetDirPath)throws IOException, FileNotFoundException, ZipException,Exception{
BufferedInputStream bis;
ZipFile zf = new ZipFile(sourceFilePath, "GBK");
Enumeration entries = zf.getEntries();
while (entries.hasMoreElements()){
ZipEntry ze = (ZipEntry) entries.nextElement();
String entryName = ze.getName();
if(entryName.contains("../")){//2016-08-25
throw new Exception("unsecurity zipfile");
}else{
String path = targetDirPath + File.separator + entryName;
Log.d("AntZipUtils", "path="+path);
if (ze.isDirectory()){
Log.d("AntZipUtils","正在创建解压目录 - " + entryName);
File decompressDirFile = new File(path);
if (!decompressDirFile.exists()){
decompressDirFile.mkdirs();
}
} else{
Log.d("AntZipUtils","正在创建解压文件 - " + entryName);
String fileDir = path.substring(0, path.lastIndexOf(File.separator));
Log.d("AntZipUtils", "fileDir="+fileDir);
File fileDirFile = new File(fileDir);
if (!fileDirFile.exists()){
fileDirFile.mkdirs();
}
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetDirPath + File.separator + entryName));
bis = new BufferedInputStream(zf.getInputStream(ze));
byte[] readContent = new byte[1024];
int readCount = bis.read(readContent);
while (readCount != -1){
bos.write(readContent, 0, readCount);
readCount = bis.read(readContent);
}
bos.close();
}
}
}
zf.close();
} }

AntZipUtils.java

在AndroidManifest.xml中添加权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.why.project.antziputilsdemo"> <!-- ======================(AntZipUtils)========================== -->
<!-- 在SD卡中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 向SD卡写入数据权限 -->
<uses-permission android:name="android.permission.REORDER_TASKS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application> </manifest>

添加运行时权限的处理(本demo中采用的是修改targetSDKVersion=22)

三、使用方法

package com.why.project.antziputilsdemo;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; import com.why.project.antziputilsdemo.utils.AntZipUtils; public class MainActivity extends AppCompatActivity { private Button btn_makeZip;
private Button btn_unZip;
private TextView tv_show; private MakeZipTask makeZipTask;//生成zip文件的异步请求类
private UnZipTask unZipTask;//解压zip文件的异步请求类 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initViews();
initEvents();
} @Override
public void onPause() {
super.onPause();
//cancel方法只是将对应的AsyncTask标记为cancel状态,并不是真正的取消线程的执行,在Java中并不能粗暴的停止线程,只能等线程执行完之后做后面的操作
if (makeZipTask != null && makeZipTask.getStatus() == AsyncTask.Status.RUNNING) {
makeZipTask.cancel(true);
}
if (unZipTask != null && unZipTask.getStatus() == AsyncTask.Status.RUNNING) {
unZipTask.cancel(true);
}
} private void initViews() {
btn_makeZip = (Button) findViewById(R.id.btn_makeZip);
btn_unZip = (Button) findViewById(R.id.btn_unZip); tv_show = (TextView) findViewById(R.id.tv_show);
} private void initEvents() {
btn_makeZip.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//生成ZIP压缩包【建议异步执行】
makeZipTask = new MakeZipTask();
makeZipTask.execute();
}
}); btn_unZip.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//解压ZIP包【建议异步执行】
unZipTask = new UnZipTask();
unZipTask.execute(); }
});
} /**
* 压缩文件的异步请求任务
*
*/
public class MakeZipTask extends AsyncTask<String, Void, String>{ @Override
protected void onPreExecute() {
//显示进度对话框
//showProgressDialog("");
tv_show.setText("正在压缩...");
} @Override
protected String doInBackground(String... params) {
String data = "";
if(! isCancelled()){
try {
String[] srcFilePaths = new String[1];
srcFilePaths[0] = Environment.getExternalStorageDirectory() + "/why";
String zipPath = Environment.getExternalStorageDirectory() + "/why.zip";
AntZipUtils.makeZip(srcFilePaths,zipPath); } catch (Exception e) {
e.printStackTrace();
}
}
return data;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(isCancelled()){
return;
}
try {
Log.w("MainActivity","result="+result);
}catch (Exception e) {
if(! isCancelled()){
//showShortToast("文件压缩失败");
tv_show.setText("文件压缩失败");
}
} finally {
if(! isCancelled()){
//隐藏对话框
//dismissProgressDialog();
tv_show.setText("压缩完成");
}
}
}
} /**
* 解压文件的异步请求任务
*
*/
public class UnZipTask extends AsyncTask<String, Void, String>{ @Override
protected void onPreExecute() {
//显示进度对话框
//showProgressDialog("");
tv_show.setText("正在解压...");
} @Override
protected String doInBackground(String... params) {
String data = "";
if(! isCancelled()){
try {
String zipPath = Environment.getExternalStorageDirectory() + "/why.zip";
String targetDirPath = Environment.getExternalStorageDirectory() + "/why";
AntZipUtils.unZip(zipPath,targetDirPath); } catch (Exception e) {
e.printStackTrace();
}
}
return data;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(isCancelled()){
return;
}
try {
Log.w("MainActivity","result="+result);
}catch (Exception e) {
if(! isCancelled()){
//showShortToast("文件解压失败");
tv_show.setText("文件解压失败");
}
} finally {
if(! isCancelled()){
//隐藏对话框
//dismissProgressDialog();
tv_show.setText("解压完成");
}
}
}
}
}

压缩文件效果:

解压文件效果:

混淆配置

#=====================基于Ant的Zip压缩工具类 =====================
#android Studio环境中不需要,eclipse环境中需要
#-libraryjars libs/ant.jar
#不混淆第三方jar包中的类
-dontwarn org.apache.tools.**
-keep class org.apache.tools.**{*;}

参考资料

Zip压缩工具类(基于JDK和基于ant.jar)

Android 解压zip文件(支持中文)

【文件压缩】 Android Jar、Zip文件压缩和解压缩处理

Android实现zip文件压缩及解压缩的方法

项目demo下载地址

https://github.com/haiyuKing/AntZipUtilsDemo

AntZipUtils【基于Ant的Zip压缩解压缩工具类】的更多相关文章

  1. Java操作zip压缩和解压缩文件工具类

    需要用到ant.jar(这里使用的是ant-1.6.5.jar) import java.io.File; import java.io.FileInputStream; import java.io ...

  2. ZIP解压缩工具类

    import java.io.File; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Expan ...

  3. GZIP压缩、解压缩工具类

    GZIP压缩.解压缩工具类: public class GZIPUtiles { public static String compress(String str) throws IOExceptio ...

  4. 使用JDK的zip编写打包工具类

    JDK自带的zip AIP在java.util.zip包下面,主要有以下几个类: java.util.zip.ZipEntryjava.util.zip.ZipInputStreamjava.util ...

  5. 基于AQS实现的Java并发工具类

    本文主要介绍一下基于AQS实现的Java并发工具类的作用,然后简单谈一下该工具类的实现原理.其实都是AQS的相关知识,只不过在AQS上包装了一下而已.本文也是基于您在有AQS的相关知识基础上,进行讲解 ...

  6. Qt之QuaZIP(zip压缩/解压缩)

    简述 QuaZIP是使用Qt/C++对ZLIB进行简单封装的用于压缩及解压缩ZIP的开源库.适用于多种平台,利用它可以很方便的将单个或多个文件打包为zip文件,且打包后的zip文件可以通过其它工具打开 ...

  7. java代理使用 apache ant实现文件压缩/解压缩

    [背景] 近日在研究web邮件下载功能,下载的邮件能够导入foxmail邮件client.可是批量下载邮件还需将邮件打成一个压缩包. 从网上搜索通过java实现文件压缩.解压缩有非常多现成的样例. [ ...

  8. Qt之zip压缩/解压缩(QuaZIP)

    摘要: 简述 QuaZIP是使用Qt/C++对ZLIB进行简单封装的用于压缩及解压缩ZIP的开源库.适用于多种平台,利用它可以很方便的将单个或多个文件打包为zip文件,且打包后的zip文件可以通过其它 ...

  9. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2 新增解压缩工具类ZipHelper

    在项目对文件进行解压缩是非常常用的功能,对文件进行压缩存储或传输可以节省流量与空间.压缩文件的格式与方法都比较多,比较常用的国际标准是zip格式.压缩与解压缩的方法也很多,在.NET 2.0开始,在S ...

随机推荐

  1. 小米笔记本怎么关闭secure boot

    关闭Secure Boot的步骤: 一.关闭 "快速启动" 功能 1.右键-开始菜单- 电源选项,进入后 点击"选择电源按钮的功能". 2.进入电源选项设置后, ...

  2. index.go

    package types type DocumentIndex struct {     // 文本的DocId     DocId uint64     // 文本的关键词长     TokenL ...

  3. bzoj5251 [2018多省省队联测]劈配

    直接网络流模拟即可AC. 可持久化+暴力=90分, 可持久化+二分=30分, 暴力加边+二分=100分. 我也很无奈啊. Ivan便涨红了脸,额上的青筋条条绽出,争辩道,“memcpy也是可持久化…… ...

  4. 本周新学的 GUI绘图技术

    作者语录:"终于学到绘图了 看到这种有图案的心情美丽多了  希望自己可以越学越多 越学越好" 本次就不用图片展示效果了,纯文字. 1.Graphics类概述 画图时我们都需要拥有一 ...

  5. Mybatis学习笔记之一(环境搭建和入门案例介绍)

    一.Mybatis概述 1.1 Mybatis介绍 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了go ...

  6. Nginx 配置 Https 免费证书访问

    配置HTTPS 现在做博客或者做网站没有 https 已经不行了,就记录一下我在腾讯云配置 https 的过程吧,非常简单,1个小时就可以了. 还涉及到 http 访问自动转发到 https 访问路径 ...

  7. 十问 JVM

    今天我们来讨论下 Java 虚拟机,通过一系列常见的问题来逐渐深入了解 JVM 创建对象过程,内存布局,类加载以及 GC 回收算法等机制. 十问 JVM 问题整理: Java虚拟机创建对象的过程 (使 ...

  8. 利用Sqoop将MySQL海量测试数据导入HDFS和HBase

    声明:作者原创,转载注明出处. 作者:帅气陈吃苹果 一.安装Sqoop 1.下载sqoop,解压.文件夹重命名 wget http://mirror.bit.edu.cn/apache/sqoop/1 ...

  9. 使用WebGL 自定义 3D 摄像头监控模型

    前言 随着视频监控联网系统的不断普及和发展, 网络摄像机更多的应用于监控系统中,尤其是高清时代的来临,更加快了网络摄像机的发展和应用. 在监控摄像机数量的不断庞大的同时,在监控系统中面临着严峻的现状问 ...

  10. 微服务(入门三):netcore ocelot api网关结合consul服务发现

    简介 api网关是提供给外部调用的统一入口,类似于dns,所有的请求统一先到api网关,由api网关进行指定内网链接. ocelot是基于netcore开发的开源API网关项目,功能强大,使用方便,它 ...