ZipExtractorTask类只能解压zip类型的压缩文件,并带有解压过程对话框,有待完善解压非zip文件的提示。
public class ZipExtractorTask extends AsyncTask<Void, Integer, Long> { private final String TAG = "ZipExtractorTask"; private File mInput; private File mOutput; private ProgressDialog mDialog; private int mProgress = 0; private Context context; private boolean deleteZip; /** *@param original 要解压的文件完整路径 * * @param purpose 解压到哪个目录 * *@param deleteZip 解压后是否删除压缩文件 * * @return This instance of ZipExtractorTask. * */ public ZipExtractorTask(Context context,String original, String purpose,boolean deleteZip){ super(); this.context = context; this.deleteZip=deleteZip; mInput = new File(original); mOutput = new File(purpose); if(!mOutput.exists()){ if(!mOutput.mkdirs()){ Log.e(TAG, "Failed to make directories:"+mOutput.getAbsolutePath()); } } if(context!=null){ mDialog = new ProgressDialog(context); } else{ mDialog = null; } } @Override protected void onPreExecute() { // TODO Auto-generated method stub Log.d(TAG,"调用onPreExecute"); if(mDialog!=null){ mDialog.setTitle("解压中..."); mDialog.setMessage(mInput.getName()); mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mDialog.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // TODO Auto-generated method stub cancel(true); } }); mDialog.show(); } } @Override protected Long doInBackground(Void... params) { // TODO Auto-generated method stub return unzip(); } @Override protected void onProgressUpdate(Integer... values) { // TODO Auto-generated method stub if(mDialog==null) return; if(values.length>1){ int max=values[1]; mDialog.setMax(max); } else mDialog.setProgress(values[0]); } @Override protected void onPostExecute(Long result) { // TODO Auto-generated method stub if (deleteZip){ mInput.delete(); } if(mDialog!=null&&mDialog.isShowing()){ mDialog.dismiss(); } mInput=null; mOutput=null; if(isCancelled()) return; } private long unzip(){ long extractedSize = 0L; Enumeration<ZipEntry> entries; //含有被压缩的文件对象(目录或文件) ZipFile zip = null; try { zip = new ZipFile(mInput,"GBK"); long uncompressedSize = getOriginalSize(zip); publishProgress(0, (int) uncompressedSize); entries = zip.getEntries(); while(entries.hasMoreElements()){ ZipEntry entry = entries.nextElement(); Log.d(TAG,"entry :"+entry.getName()); if(entry.isDirectory()){ continue; //目录内的文件对象会在下次遍历中会出现 } File destination = new File(mOutput, entry.getName()); //每个文件的存放路径,包括文件夹内的 if(!destination.getParentFile().exists()){ Log.e(TAG, "make="+destination.getParentFile().getAbsolutePath()); destination.getParentFile().mkdirs(); } ProgressReportingOutputStream outStream = new ProgressReportingOutputStream(destination); extractedSize+=save(zip.getInputStream(entry),outStream); outStream.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if (zip != null) { zip.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return extractedSize; } /** * * @param file 压缩文件对象 * @return 放回压缩文件的原始大小 */ private long getOriginalSize(ZipFile file){ Enumeration<ZipEntry> entries = file.getEntries(); long originalSize = 0L; while(entries.hasMoreElements()){ ZipEntry entry = entries.nextElement(); if(entry.getSize()>=0){ originalSize+=entry.getSize(); } } return originalSize; } /** * 该方法主要是将压缩文件内的所有对象提取保存到指定路径 * @param input 输入路 * @param output 封装好的可以记录解压进度的输出流 * @return 统计缓存大小 */ private int save(InputStream input, OutputStream output){ byte[] buffer = new byte[1024*8]; BufferedInputStream in = new BufferedInputStream(input, 1024*8); BufferedOutputStream out = new BufferedOutputStream(output, 1024*8); int count =0,n; try { while((n=in.read(buffer, 0, 1024*8))!=-1){ out.write(buffer, 0, n); count+=n; } out.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { out.close(); in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return count; } private final class ProgressReportingOutputStream extends FileOutputStream{ public ProgressReportingOutputStream(File file) throws FileNotFoundException { super(file); // TODO Auto-generated constructor stub } @Override public void write(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException { // TODO Auto-generated method stub super.write(buffer, byteOffset, byteCount); mProgress += byteCount; publishProgress(mProgress); } } }
为了解决解压后的文件名出现中文乱码,不使用java.util.zip包下的类(某些方法所需API等级较高),改用第三方ZipEntry.jar对应的类。ZipEntry.jar下载地址
注:window下zip压缩文件名采用GBK编码方式(ios为utf-8,linux不知),而ZipFile默认采用UTF-8方式解码文件名,所以构造ZipFile对象时要指定GBK;