package com.zhan_dui.dictionary.utils; 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.zip.ZipEntry; import java.util.zip.ZipInputStream; import android.os.AsyncTask; /** * 解压缩文件工具类 * * @author xuanqinanhai * */ public class UnzipUtils { public interface UnzipInterface { /** * beforeUnzip 在Unzip之前做的事情 * * @param source * 源文件地址 * @param outputDirectory * 带解压目录 */ public boolean beforeUnzip(String source, String outputDirectory); /** * afterUnzip unzip结束时执行的函数 UI线程 * * @param result * 解压结果 true为成功,false为失败 * @param source * 源文件地址 * @param outputDirectory * 解压目标文件夹地址 */ public void afterUnzip(Boolean result, String source, String outputDirectory); /** * errorOccur 出错时调用该函数 UI线程 * * @param errorMsg * 错误信息 * @param source * 源文件地址 * @param outputDirectory * 解压目标文件夹地址 */ /** * beforeUnzipThread 线程开始前 线程级别,不要做UI操作 */ public void beforeUnzipThread(String source, String outputDirectory); /** * afterUnzipThread 线程结束前 线程级别,不要做UI操作 * * @param result * 是否出错 * @param source * 源地址 * @param outputDirectory * 解压目标地址 */ public void afterUnzipThread(Boolean result, String source, String outputDirectory); public void errorOccur(String errorMsg, String source, String outputDirectory); /** * onZipStart 在解压开始时调用 UI线程 * * @param source * @param outputDirectory */ } public static final String CREATE_DIRECTORY_ERROR = "无法创建解压文件夹"; public static final String FILE_NOT_EXSIT = "待解压的文件不存在"; public static final String ZIP_POINT_ERROR = "目标文件地址不是压缩文件或者已经被损坏"; public static final String ZIP_OUTPUTSTREAM_ERROR = "无法创建要解压的目标文件"; public static final String FILESTREAM_CANNOT_CLOSE = "文件流无法关闭"; public static final String ZIP_NEXT_POINT_ERROR = "无法定位到下一个解压点"; public static final String ABORT = "已经被用户取消"; public static final String BEFORE_TASK_STOP = "before函数结束了解压"; public static void unzipFile(UnzipInterface unzipBehavior, String source, String outputDirectory, Boolean rewrite) { new UnzipTask(source, outputDirectory, unzipBehavior, rewrite) .execute(); } private static class UnzipTask extends AsyncTask<Void, Integer, Boolean> { private String source; private String outputDirectory; private UnzipInterface unzipBehavior; private Boolean rewrite; private String errorMsg = null; private boolean stop = false; public UnzipTask(String source, String outputDirectory, UnzipInterface unzipBehavior, Boolean rewrite) { super(); this.source = source; this.outputDirectory = outputDirectory; this.unzipBehavior = unzipBehavior; this.rewrite = rewrite; } @Override protected void onPreExecute() { super.onPreExecute(); // 如果before的工作返回false则不开始解压 stop = !unzipBehavior.beforeUnzip(source, outputDirectory); } @SuppressWarnings("resource") @Override protected Boolean doInBackground(Void... params) { if (stop) { errorMsg = BEFORE_TASK_STOP; return false; } unzipBehavior.beforeUnzipThread(source, outputDirectory); // 创建解压目标目录 File file = new File(outputDirectory); // 如果目标目录不存在,则创建 if (!file.exists()) { if (file.mkdirs() == false) { errorMsg = CREATE_DIRECTORY_ERROR; unzipBehavior.afterUnzipThread(false, source, outputDirectory); return false; } } InputStream inputStream; try { inputStream = new FileInputStream(new File(source)); } catch (FileNotFoundException e) { e.printStackTrace(); errorMsg = FILE_NOT_EXSIT; unzipBehavior.afterUnzipThread(false, source, outputDirectory); return false; } // 打开压缩文件 ZipInputStream zipInputStream = new ZipInputStream(inputStream); ZipEntry zipEntry = null; try { zipEntry = zipInputStream.getNextEntry(); } catch (IOException e) { e.printStackTrace(); errorMsg = ZIP_POINT_ERROR; unzipBehavior.afterUnzipThread(false, source, outputDirectory); return false; } byte[] buffer = new byte[1024]; // 解压时字节计数 int count = 0; // 如果进入点为空说明已经遍历完所有压缩包中文件和目录 while (zipEntry != null) { // 如果是一个目录 if (zipEntry.isDirectory()) { file = new File(outputDirectory + File.separator + zipEntry.getName()); // 文件需要覆盖或者是文件不存在 if (rewrite || !file.exists()) { file.mkdir(); } } else { // 如果是文件 file = new File(outputDirectory + File.separator + zipEntry.getName()); // 文件需要覆盖或者文件不存在,则解压文件 FileOutputStream fileOutputStream = null; if (rewrite || !file.exists()) { try { file.createNewFile(); fileOutputStream = new FileOutputStream(file); while ((count = zipInputStream.read(buffer)) > 0) { fileOutputStream.write(buffer, 0, count); if (stop) { errorMsg = ABORT; return false; } } } catch (IOException e) { e.printStackTrace(); errorMsg = ZIP_OUTPUTSTREAM_ERROR; unzipBehavior.afterUnzipThread(false, source, outputDirectory); return false; } try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); errorMsg = FILESTREAM_CANNOT_CLOSE; unzipBehavior.afterUnzipThread(false, source, outputDirectory); return false; } } } // 定位到下一个文件入口 try { zipEntry = zipInputStream.getNextEntry(); } catch (IOException e) { e.printStackTrace(); errorMsg = ZIP_NEXT_POINT_ERROR; unzipBehavior.afterUnzipThread(false, source, outputDirectory); return false; } } unzipBehavior.afterUnzipThread(true, source, outputDirectory); return true; } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (result == false) { unzipBehavior.errorOccur(errorMsg, source, outputDirectory); } unzipBehavior.afterUnzip(result, source, outputDirectory); } } }