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;