策略模式:
1、首先定义解压算法的接口
public interface IUnZip { public void unZip(File zipFile, String folderPath, UnZipCallBack callback)throws ZipException, IOException; }
2、定义一个默认的算法实现类
public class DefaultUnziper implements IUnZip { //substr = new String(substr.getBytes("8859_1"), "GB2312"); private static final String byteformat="UTF-8"; private static final String resultformat="UTF-8"; /** * 删除文件,如果包含文件目录 则递归删除 * * @param dir 文件File 如:File dir = new File(SDPATH+File.separator+"Test.zip"); * @return */ public static boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i = 0; i < children.length; i++) { boolean success = deleteDir(new File(dir, children[i])); if (!success) { return false; } } } return dir.delete(); } /** * @param zipFile 要解压的文件 * @param folderPath 解压后文件的存放目标路径 * @return * @throws ZipException * @throws IOException */ @Override public void unZip(File zipFile, String folderPath, UnZipCallBack callback) throws ZipException, IOException { String dirName = null; ZipFile zfile = new ZipFile(zipFile); Enumeration zList = zfile.entries();// 返回 ZIP 文件条目的枚举。 int file_max = zfile.size();//ZIP 文件中的条目数。 int progress = 0;//解压进度 ZipEntry ze = null; byte[] buf = new byte[1024]; while (zList.hasMoreElements()) {// 当且仅当此枚举对象至少还包含一个可提供的元素时,才返回 true;否则返回 false。 ze = (ZipEntry) zList.nextElement();//获得压缩文件里 所有的文件 和文件目录 progress++; if (ze.isDirectory()) {// 当且仅当此抽象路径名表示的文件存在且 是一个目录时,返回 true;否则返回false continue;//是目录则返回 } File myfile = getRealFileName(folderPath, ze.getName()); if (myfile != null) { OutputStream os = new BufferedOutputStream(new FileOutputStream(myfile));//ze.getName()是获得压缩文件中的文件路径 不包括文件夹 InputStream is = new BufferedInputStream(zfile.getInputStream(ze)); int readLen = 0; while ((readLen = is.read(buf, 0, 1024)) != -1) { os.write(buf, 0, readLen); } is.close(); os.close(); } else { //文件损坏 callback.run(0, -3, "null");//回调接口 } //String Str1 = dirName != null ? dirName.substring(0, dirName.indexOf("/")) : "null"; if (progress <= file_max) { dirName = ze.getName(); String Str1 = dirName != null ? dirName.substring(0, dirName.indexOf("/")+1) : "null"; callback.run(file_max, progress, Str1);//回调接口 } } zfile.close(); } /** * 给定根目录,返回一个相对路径所对应的实际文件名. * * @param folderPath 指定根目录 * @param absFileName 相对路径名,来自于ZipEntry中的name * @return java.io.File 实际的文件 */ private File getRealFileName(String folderPath, String absFileName) { String[] dirs = absFileName.split("/"); // System.out.println("dirs-->"+dirs.length); // System.out.println("dirs-->"+dirs[0]); File ret = new File(folderPath); String substr = null; if (dirs.length > 1) { for (int i = 0; i < dirs.length - 1; i++) {//循环拼文件路径 substr = dirs[i]; try { substr = new String(substr.getBytes(byteformat), resultformat); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret = new File(ret, substr); } if (!ret.exists()) ret.mkdirs();//如果目录不存在则创建目录 ,包括他的父目录 substr = dirs[dirs.length - 1];//为文件名, 不是目录 try { substr = new String(substr.getBytes(byteformat), resultformat); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret = new File(ret, substr); return ret; } else if (dirs.length == 1) {//当解压的文件没有目录时 substr = dirs[0]; try { substr = new String(substr.getBytes(byteformat), resultformat); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } ret = new File(ret, substr); return ret; } return ret; } }
3、定义解压时的回调
public interface UnZipCallBack { void run(int max, int progress, String dirName); }
4、定义解压器,解压器持有解压算法的引用,通过构造方法传入不同的实现类实现不同的解压机制,但不影响整体代码的逻辑,避免牵一发而动全身的现象发生
public class UnZipper { private IUnZip unziper; /** * * @param unziper 解压算法实现类 */ public UnZipper(IUnZip unziper) { // TODO Auto-generated constructor stub this.unziper=unziper; } public void doingUnZip(File zipFile, String folderPath, UnZipCallBack callBack) throws IOException{ if(unziper!=null)unziper.unZip(zipFile,folderPath, callBack); } }
5、定义解压线程
public class UnZipRunable implements Runnable{ private String zip_path; private String folderPath; private UnZipper unZipper; private UnZipCallBack callBack; public UnZipRunable(String zip_path, String folderPath, UnZipper unZipContext, UnZipCallBack callBack) { super(); this.zip_path = zip_path; this.folderPath = folderPath; this.unZipper = unZipContext; this.callBack = callBack; } @Override public void run(){ // TODO Auto-generated method stub File zipFile=new File(zip_path); try { unZipper.doingUnZip(zipFile, folderPath, callBack); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }