首页 > 代码库 > AntZipUtils【基于Ant的Zip压缩解压缩工具类】

AntZipUtils【基于Ant的Zip压缩解压缩工具类】

版权声明:本文为博主原创文章,未经博主允许不得转载。

前言

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压缩解压缩工具类】