zoukankan      html  css  js  c++  java
  • AntZipUtils【基于Ant的Zip压缩解压缩工具类】

    版权声明:本文为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

  • 相关阅读:
    CDH 2、Cloudera Manager的安装
    204 01 Android 零基础入门 03 Java常用工具类 04 Java集合 04 Map集合 01 Map概述
    203 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 07 删除宠物猫信息数据(引入泛型知识点)
    202 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 06 查找宠物猫信息数据
    201 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 05 添加重复的宠物猫信息数据
    200 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 04 添加和显式宠物猫信息
    199 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 03 宠物猫信息管理概述
    198 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 02 案例:在集合中插入字符串
    197 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 01 Set概述
    196 01 Android 零基础入门 03 Java常用工具类 04 Java集合 02 List集合 05 案例:公告的删除和修改
  • 原文地址:https://www.cnblogs.com/whycxb/p/7182647.html
Copyright © 2011-2022 走看看