版权声明:本文为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文件复制到项目中

  1. package com.why.project.antziputilsdemo.utils;
  2.  
  3. import android.util.Log;
  4. import org.apache.tools.zip.ZipEntry;
  5. import org.apache.tools.zip.ZipFile;
  6. import org.apache.tools.zip.ZipOutputStream;
  7. import java.io.BufferedInputStream;
  8. import java.io.BufferedOutputStream;
  9. import java.io.File;
  10. import java.io.FileInputStream;
  11. import java.io.FileNotFoundException;
  12. import java.io.FileOutputStream;
  13. import java.io.IOException;
  14. import java.io.InputStream;
  15. import java.util.Enumeration;
  16. import java.util.zip.ZipException;
  17. /**
  18. * @Create By HaiyuKing
  19. * @Used 基于Ant的Zip压缩工具类
  20. * @参考资料 http://yunzhu.iteye.com/blog/1480293
  21. * http://www.cnblogs.com/wainiwann/archive/2013/07/17/3196196.html
  22. * http://blog.csdn.net/growing_tree/article/details/46009813
  23. * http://www.jb51.net/article/69773.htm
  24. */
  25. public class AntZipUtils {
  26.  
  27. public static final String ENCODING_DEFAULT = "UTF-8";
  28.  
  29. public static final int BUFFER_SIZE_DIFAULT = 1024;
  30.  
  31. /**生成ZIP压缩包【建议异步执行】
  32. * @param srcFilePaths - 要压缩的文件路径字符串数组【如果压缩一个文件夹,则只需要把文件夹目录放到一个数组中即可】
  33. * @param zipPath - 生成的Zip路径*/
  34. public static void makeZip(String[] srcFilePaths, String zipPath)throws Exception {
  35. makeZip(srcFilePaths, zipPath, ENCODING_DEFAULT);
  36. }
  37.  
  38. /**生成ZIP压缩包【建议异步执行】
  39. * @param srcFilePaths - 要压缩的文件路径字符串数组
  40. * @param zipPath - 生成的Zip路径
  41. * @param encoding - 编码格式*/
  42. public static void makeZip(String[] srcFilePaths, String zipPath,String encoding) throws Exception {
  43. File[] inFiles = new File[srcFilePaths.length];
  44. for (int i = 0; i < srcFilePaths.length; i++) {
  45. inFiles[i] = new File(srcFilePaths[i]);
  46. }
  47. makeZip(inFiles, zipPath, encoding);
  48. }
  49.  
  50. /**生成ZIP压缩包【建议异步执行】
  51. * @param srcFiles - 要压缩的文件数组
  52. * @param zipPath - 生成的Zip路径*/
  53. public static void makeZip(File[] srcFiles, String zipPath) throws Exception {
  54. makeZip(srcFiles, zipPath, ENCODING_DEFAULT);
  55. }
  56.  
  57. /**生成ZIP压缩包【建议异步执行】
  58. * @param srcFiles - 要压缩的文件数组
  59. * @param zipPath - 生成的Zip路径
  60. * @param encoding - 编码格式*/
  61. public static void makeZip(File[] srcFiles, String zipPath, String encoding)
  62. throws Exception {
  63. ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipPath)));
  64. zipOut.setEncoding(encoding);
  65. for (int i = 0; i < srcFiles.length; i++) {
  66. File file = srcFiles[i];
  67. doZipFile(zipOut, file, file.getParent());
  68. }
  69. zipOut.flush();
  70. zipOut.close();
  71. }
  72.  
  73. private static void doZipFile(ZipOutputStream zipOut, File file, String dirPath) throws FileNotFoundException, IOException {
  74. if (file.isFile()) {
  75. BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
  76. String zipName = file.getPath().substring(dirPath.length());
  77. while (zipName.charAt(0) == '\\' || zipName.charAt(0) == '/') {
  78. zipName = zipName.substring(1);
  79. }
  80. ZipEntry entry = new ZipEntry(zipName);
  81. zipOut.putNextEntry(entry);
  82. byte[] buff = new byte[BUFFER_SIZE_DIFAULT];
  83. int size;
  84. while ((size = bis.read(buff, 0, buff.length)) != -1) {
  85. zipOut.write(buff, 0, size);
  86. }
  87. zipOut.closeEntry();
  88. bis.close();
  89. } else {
  90. File[] subFiles = file.listFiles();
  91. for (File subFile : subFiles) {
  92. doZipFile(zipOut, subFile, dirPath);
  93. }
  94. }
  95. }
  96.  
  97. /**解压ZIP包【建议异步执行】
  98. * @param zipFilePath ZIP包的路径
  99. * @param targetDirPath 指定的解压缩文件夹地址 */
  100. public static void unZip(String zipFilePath, String targetDirPath)throws IOException,Exception {
  101. unZip(new File(zipFilePath), targetDirPath);
  102. }
  103.  
  104. /**解压ZIP包【建议异步执行】
  105. * @param zipFile ZIP包的文件
  106. * @param targetDirPath 指定的解压缩目录地址 */
  107. public static void unZip(File zipFile, String targetDirPath) throws IOException,Exception {
  108. //先删除,后添加
  109. if (new File(targetDirPath).exists()) {
  110. new File(targetDirPath).delete();
  111. }
  112. new File(targetDirPath).mkdirs();
  113.  
  114. ZipFile zip = new ZipFile(zipFile);
  115. Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.getEntries();
  116. while (entries.hasMoreElements()) {
  117. ZipEntry zipEntry = entries.nextElement();
  118. if (zipEntry.isDirectory()) {
  119. // TODO
  120. } else {
  121. String zipEntryName = zipEntry.getName();
  122. if(zipEntryName.contains("../")){//2016-08-25
  123. throw new Exception("unsecurity zipfile");
  124. }else{
  125. if (zipEntryName.indexOf(File.separator) > 0) {
  126. String zipEntryDir = zipEntryName.substring(0, zipEntryName.lastIndexOf(File.separator) + 1);
  127. String unzipFileDir = targetDirPath + File.separator + zipEntryDir;
  128. File unzipFileDirFile = new File(unzipFileDir);
  129. if (!unzipFileDirFile.exists()) {
  130. unzipFileDirFile.mkdirs();
  131. }
  132. }
  133.  
  134. InputStream is = zip.getInputStream(zipEntry);
  135. FileOutputStream fos = new FileOutputStream(new File(targetDirPath + File.separator + zipEntryName));
  136. byte[] buff = new byte[BUFFER_SIZE_DIFAULT];
  137. int size;
  138. while ((size = is.read(buff)) > 0) {
  139. fos.write(buff, 0, size);
  140. }
  141. fos.flush();
  142. fos.close();
  143. is.close();
  144. }
  145. }
  146. }
  147. }
  148.  
  149. /**
  150. * 使用Apache工具包解压缩zip文件 【使用Java的zip包可以进行简单的文件压缩和解压缩处理时,但是遇到包含中文汉字目录或者包含多层子目录的复杂目录结构时,容易出现各种各样的问题。】
  151. * @param sourceFilePath 指定的解压缩文件地址
  152. * @param targetDirPath 指定的解压缩目录地址
  153. * @throws IOException
  154. * @throws FileNotFoundException
  155. * @throws ZipException
  156. */
  157. public static void uncompressFile(String sourceFilePath, String targetDirPath)throws IOException, FileNotFoundException, ZipException,Exception{
  158. BufferedInputStream bis;
  159. ZipFile zf = new ZipFile(sourceFilePath, "GBK");
  160. Enumeration entries = zf.getEntries();
  161. while (entries.hasMoreElements()){
  162. ZipEntry ze = (ZipEntry) entries.nextElement();
  163. String entryName = ze.getName();
  164. if(entryName.contains("../")){//2016-08-25
  165. throw new Exception("unsecurity zipfile");
  166. }else{
  167. String path = targetDirPath + File.separator + entryName;
  168. Log.d("AntZipUtils", "path="+path);
  169. if (ze.isDirectory()){
  170. Log.d("AntZipUtils","正在创建解压目录 - " + entryName);
  171. File decompressDirFile = new File(path);
  172. if (!decompressDirFile.exists()){
  173. decompressDirFile.mkdirs();
  174. }
  175. } else{
  176. Log.d("AntZipUtils","正在创建解压文件 - " + entryName);
  177. String fileDir = path.substring(0, path.lastIndexOf(File.separator));
  178. Log.d("AntZipUtils", "fileDir="+fileDir);
  179. File fileDirFile = new File(fileDir);
  180. if (!fileDirFile.exists()){
  181. fileDirFile.mkdirs();
  182. }
  183. BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetDirPath + File.separator + entryName));
  184. bis = new BufferedInputStream(zf.getInputStream(ze));
  185. byte[] readContent = new byte[1024];
  186. int readCount = bis.read(readContent);
  187. while (readCount != -1){
  188. bos.write(readContent, 0, readCount);
  189. readCount = bis.read(readContent);
  190. }
  191. bos.close();
  192. }
  193. }
  194. }
  195. zf.close();
  196. }
  197.  
  198. }

AntZipUtils.java

在AndroidManifest.xml中添加权限

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.why.project.antziputilsdemo">
  4.  
  5. <!-- ======================(AntZipUtils)========================== -->
  6. <!-- 在SD卡中创建与删除文件权限 -->
  7. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
  8. <!-- 向SD卡写入数据权限 -->
  9. <uses-permission android:name="android.permission.REORDER_TASKS"/>
  10. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  11. <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
  12. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  13.  
  14. <application
  15. android:allowBackup="true"
  16. android:icon="@mipmap/ic_launcher"
  17. android:label="@string/app_name"
  18. android:supportsRtl="true"
  19. android:theme="@style/AppTheme">
  20. <activity android:name=".MainActivity">
  21. <intent-filter>
  22. <action android:name="android.intent.action.MAIN"/>
  23.  
  24. <category android:name="android.intent.category.LAUNCHER"/>
  25. </intent-filter>
  26. </activity>
  27. </application>
  28.  
  29. </manifest>

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

三、使用方法

  1. package com.why.project.antziputilsdemo;
  2.  
  3. import android.os.AsyncTask;
  4. import android.os.Bundle;
  5. import android.os.Environment;
  6. import android.support.v7.app.AppCompatActivity;
  7. import android.util.Log;
  8. import android.view.View;
  9. import android.widget.Button;
  10. import android.widget.TextView;
  11.  
  12. import com.why.project.antziputilsdemo.utils.AntZipUtils;
  13.  
  14. public class MainActivity extends AppCompatActivity {
  15.  
  16. private Button btn_makeZip;
  17. private Button btn_unZip;
  18. private TextView tv_show;
  19.  
  20. private MakeZipTask makeZipTask;//生成zip文件的异步请求类
  21. private UnZipTask unZipTask;//解压zip文件的异步请求类
  22.  
  23. @Override
  24. protected void onCreate(Bundle savedInstanceState) {
  25. super.onCreate(savedInstanceState);
  26. setContentView(R.layout.activity_main);
  27.  
  28. initViews();
  29. initEvents();
  30. }
  31.  
  32. @Override
  33. public void onPause() {
  34. super.onPause();
  35. //cancel方法只是将对应的AsyncTask标记为cancel状态,并不是真正的取消线程的执行,在Java中并不能粗暴的停止线程,只能等线程执行完之后做后面的操作
  36. if (makeZipTask != null && makeZipTask.getStatus() == AsyncTask.Status.RUNNING) {
  37. makeZipTask.cancel(true);
  38. }
  39. if (unZipTask != null && unZipTask.getStatus() == AsyncTask.Status.RUNNING) {
  40. unZipTask.cancel(true);
  41. }
  42. }
  43.  
  44. private void initViews() {
  45. btn_makeZip = (Button) findViewById(R.id.btn_makeZip);
  46. btn_unZip = (Button) findViewById(R.id.btn_unZip);
  47.  
  48. tv_show = (TextView) findViewById(R.id.tv_show);
  49. }
  50.  
  51. private void initEvents() {
  52. btn_makeZip.setOnClickListener(new View.OnClickListener() {
  53. @Override
  54. public void onClick(View v) {
  55. //生成ZIP压缩包【建议异步执行】
  56. makeZipTask = new MakeZipTask();
  57. makeZipTask.execute();
  58. }
  59. });
  60.  
  61. btn_unZip.setOnClickListener(new View.OnClickListener() {
  62. @Override
  63. public void onClick(View v) {
  64. //解压ZIP包【建议异步执行】
  65. unZipTask = new UnZipTask();
  66. unZipTask.execute();
  67.  
  68. }
  69. });
  70. }
  71.  
  72. /**
  73. * 压缩文件的异步请求任务
  74. *
  75. */
  76. public class MakeZipTask extends AsyncTask<String, Void, String>{
  77.  
  78. @Override
  79. protected void onPreExecute() {
  80. //显示进度对话框
  81. //showProgressDialog("");
  82. tv_show.setText("正在压缩...");
  83. }
  84.  
  85. @Override
  86. protected String doInBackground(String... params) {
  87. String data = "";
  88. if(! isCancelled()){
  89. try {
  90. String[] srcFilePaths = new String[1];
  91. srcFilePaths[0] = Environment.getExternalStorageDirectory() + "/why";
  92. String zipPath = Environment.getExternalStorageDirectory() + "/why.zip";
  93. AntZipUtils.makeZip(srcFilePaths,zipPath);
  94.  
  95. } catch (Exception e) {
  96. e.printStackTrace();
  97. }
  98. }
  99. return data;
  100. }
  101. @Override
  102. protected void onPostExecute(String result) {
  103. super.onPostExecute(result);
  104. if(isCancelled()){
  105. return;
  106. }
  107. try {
  108. Log.w("MainActivity","result="+result);
  109. }catch (Exception e) {
  110. if(! isCancelled()){
  111. //showShortToast("文件压缩失败");
  112. tv_show.setText("文件压缩失败");
  113. }
  114. } finally {
  115. if(! isCancelled()){
  116. //隐藏对话框
  117. //dismissProgressDialog();
  118. tv_show.setText("压缩完成");
  119. }
  120. }
  121. }
  122. }
  123.  
  124. /**
  125. * 解压文件的异步请求任务
  126. *
  127. */
  128. public class UnZipTask extends AsyncTask<String, Void, String>{
  129.  
  130. @Override
  131. protected void onPreExecute() {
  132. //显示进度对话框
  133. //showProgressDialog("");
  134. tv_show.setText("正在解压...");
  135. }
  136.  
  137. @Override
  138. protected String doInBackground(String... params) {
  139. String data = "";
  140. if(! isCancelled()){
  141. try {
  142. String zipPath = Environment.getExternalStorageDirectory() + "/why.zip";
  143. String targetDirPath = Environment.getExternalStorageDirectory() + "/why";
  144. AntZipUtils.unZip(zipPath,targetDirPath);
  145.  
  146. } catch (Exception e) {
  147. e.printStackTrace();
  148. }
  149. }
  150. return data;
  151. }
  152. @Override
  153. protected void onPostExecute(String result) {
  154. super.onPostExecute(result);
  155. if(isCancelled()){
  156. return;
  157. }
  158. try {
  159. Log.w("MainActivity","result="+result);
  160. }catch (Exception e) {
  161. if(! isCancelled()){
  162. //showShortToast("文件解压失败");
  163. tv_show.setText("文件解压失败");
  164. }
  165. } finally {
  166. if(! isCancelled()){
  167. //隐藏对话框
  168. //dismissProgressDialog();
  169. tv_show.setText("解压完成");
  170. }
  171. }
  172. }
  173. }
  174. }

压缩文件效果:

解压文件效果:

混淆配置

  1. #=====================基于Ant的Zip压缩工具类 =====================
  2. #android Studio环境中不需要,eclipse环境中需要
  3. #-libraryjars libs/ant.jar
  4. #不混淆第三方jar包中的类
  5. -dontwarn org.apache.tools.**
  6. -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. 【BZOJ 2713】[Violet 2]愚蠢的副官&&【BZOJ1183】[Croatian2008]Umnozak——【数位DP】

    题目链接: 2713传送门 1183传送! 题解: 由于看不懂英文题解(十个单词十一个不认识……),所以只能自己想QAQ. 其实乱搞就好= =. 首先我们发现,各位数字乘积要在1e9以下才可能有用,这 ...

  3. Java线程与Linux内核线程的映射关系

    Linux从内核2.6开始使用NPTL (Native POSIX Thread Library)支持,但这时线程本质上还轻量级进程. Java里的线程是由JVM来管理的,它如何对应到操作系统的线程是 ...

  4. springcloud学习资料汇总

    收集Spring Cloud相关的学习资料 学习Spring Cloud首先需要了解Spring Boot,不了解Spring Boot的同学戳这里Spring Boot学习资料汇总 重点推荐:Spr ...

  5. Https协议与HttpClient的实现

    一.背景 HTTP是一个传输内容有可读性的公开协议,客户端与服务器端的数据完全通过明文传输.在这个背景之下,整个依赖于Http协议的互联网数据都是透明的,这带来了很大的数据安全隐患.想要解决这个问题有 ...

  6. Go中原始套接字的深度实践

    1. 介绍 2. 传输层socket 2.1 ICMP 2.2 TCP 2.3 传输层协议 3. 网络层socket 3.1 使用Go库 3.2 系统调用 3.3 网络层协议 4. 总结 4.1 参考 ...

  7. Python爬虫实践 -- 记录我的第二只爬虫

    1.爬虫基本原理 我们爬取中国电影最受欢迎的影片<红海行动>的相关信息.其实,爬虫获取网页信息和人工获取信息,原理基本是一致的. 人工操作步骤: 1. 获取电影信息的页面 2. 定位(找到 ...

  8. Spark学习之数据读取与保存总结(二)

    8.Hadoop输入输出格式 除了 Spark 封装的格式之外,也可以与任何 Hadoop 支持的格式交互.Spark 支持新旧两套Hadoop 文件 API,提供了很大的灵活性. 要使用新版的 Ha ...

  9. netty 之 telnet HelloWorld 详解

    前言 Netty是 一个异步事件驱动的网络应用程序框架, 用于快速开发可维护的高性能协议服务器和客户端. etty是一个NIO客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序.它极 ...

  10. 这可能是史上最好的 Java8 新特性 Stream 流教程

    本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...