• 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

  • 相关阅读:
    LR遇到的问题
    常用的mysql操作
    mysql操作
    土地档案管理系统架构图,ER图,用例图
    土地档案管理系统需求分析
    Load data local infile
    Lamda Expression
    Domain Logic approaches
    Spring AOP Capabilities and Goals
    python
  • 原文地址:https://www.cnblogs.com/whycxb/p/7182647.html
Copyright © 2020-2023  润新知