使用Java操作zip文件
Java提供了操作zip文件的API,具体来说,它们位于:java.util.zip 包中,以下的两个工具类分别用于创建zip文件、展开(解压缩)zip文件。
创建zip文件的助手类:
/** * @author INC062805 * */ public class ZipHelper { // 静态创建起 public static ZipHelper create(File input, File output) { // 检查参数 if (input == null || !input.exists()) { throw new IllegalArgumentException("input is NULL or not exist!"); } if (output == null) { throw new IllegalArgumentException("output can not be NULL!"); } return new ZipHelper(input, output); } // 隐藏构建器 ZipHelper(File input, File output) { this.input = input; this.output = output; } // 开始执行压缩 public boolean start() { OutputStream out = null; try { out = new BufferedOutputStream(new FileOutputStream(output)); ZipOutputStream zipOut = new ZipOutputStream(out); zipOut.setLevel(ZipEntry.STORED); zip(zipOut, input, input); zipOut.flush(); zipOut.finish(); zipOut.close(); return true; } catch (Exception e) { // e.printStackTrace(); return false; } finally { IOUtils.quietCloseOutputStream(out); } } // 执行压缩,input:输入文件(可以是目录),rootDir:起始目录 private void zip(ZipOutputStream out, File input, File rootDir) throws IOException { if (input == null || !input.exists()) { return; } if (input.isDirectory()) { zipDirectory(out, input, rootDir); } else { zipFile(out, input, rootDir); } } // 向ZipOutputStream中添加目录,dir:输入目录,rootDir:起始目录 private void zipDirectory(ZipOutputStream out, File dir, File rootDir) throws IOException { // 检查input目录,是否是系统顶级目标,例如:c:\ or / if (rootDir.getParentFile() == null) { // SKIP ROOT DIR } if (!onlyFile) { String name = getEntryNameString(dir, rootDir) + '/'; out.putNextEntry(new ZipEntry(name)); // System.out.println("zip.dir:" + entry.getName()); } File[] files = dir.listFiles(); for (File f : files) { zip(out, f, rootDir); } } // 向ZipOutputStream中 添加文件 private void zipFile(ZipOutputStream out, File file, File rootDir) throws IOException { // ZipEntry entry = new ZipEntry(getEntryNameString(file, rootDir)); out.putNextEntry(entry); InputStream in = null; try { in = new FileInputStream(file); IOUtils.copy(in, out); out.closeEntry(); // System.out.println("zip.file:" + entry.getName()); } finally { IOUtils.quietCloseInputStream(in); } } // 通过输入文件(名称),取得在Zip Entry中应该有的名称 private String getEntryNameString(final File input, final File rootDir) { if (onlyFile) { return input.getName(); } // 检查是否是root if (input.equals(rootDir)) { return input.getName(); } // 确认回溯前的起始位置 final File parent = rootDir.getParentFile(); File file = input; // 回溯 直到找到 root StringBuilder ret = new StringBuilder(); do { if (ret.length() > 0) { ret.insert(0, '/'); } ret.insert(0, file.getName()); file = file.getParentFile(); } while (file != null && !file.equals(parent)); return ret.toString(); } // 是否更新已存在的输出文件 // private boolean update = false; // 是否仅仅打包文件,忽略目录结构 private boolean onlyFile = false; // 输入输出 private final File input; private final File output; public boolean isOnlyFile() { return onlyFile; } public void setOnlyFile(boolean onlyFile) { this.onlyFile = onlyFile; } }
展开zip文件的助手类:
/** * @author INC062805 * * 展开zip文件的助手类 */ public class UnZipHelper { // public static UnZipHelper create(File srcZipFile, File destDir) { return new UnZipHelper(srcZipFile, destDir); } // private File srcZipFile, destDir; private CharSequence error = null; // 隐藏构建器 private UnZipHelper(File srcZipFile, File destDir) { this.srcZipFile = srcZipFile; this.destDir = destDir; } // 取得错误信息 public CharSequence getErrorInfo() { return error; } // 展开src 指定的zip文件到 目标位置dest public boolean start() { return start(true); } // 展开src 指定的zip文件到 目标位置dest,并自动创建顶级目录 public boolean start(boolean autoCreateTopDir) { // 自动创建顶级目录 --- 与zip文件同名 if (autoCreateTopDir) { String name = srcZipFile.getName(); // 析除扩展名 int pos = name.lastIndexOf('.'); if (pos > 0) { name = name.substring(0, pos); } destDir = new File(destDir, name); destDir.mkdirs(); } try { ZipFile zf = new ZipFile(srcZipFile); Enumeration extends ZipEntry> e = zf.entries(); boolean bool = false; while (e.hasMoreElements()) { ZipEntry ze = e.nextElement(); // 处理目录 if (ze.isDirectory()) { bool = expandDirectory(ze, destDir); continue; } // 处理文件 bool = expandFile(zf, ze, destDir); } return bool; } catch (Exception e) { error = "open zipfile Error:(" + e.getLocalizedMessage() + ")"; return false; } } // 解压缩目录元素 到目标位置 private boolean expandDirectory(ZipEntry ze, File destDir) { File dir = new File(destDir, ze.getName()); boolean bool = dir.exists() ? true : dir.mkdirs(); // System.out.println("Expand.Dir:" + dir.getAbsolutePath()); if (!bool) { error = "create Dest Directory Error,:-("; } return bool; } // 解压缩文件元素到目标目录下 private boolean expandFile(ZipFile zf, ZipEntry ze, File destDir) { // 定位到目标目录 String name = ze.getName(); File dir = locateDestDirectory(name, destDir); // 确认目标文件位置 int pos = name.lastIndexOf('/'); if (pos > 0) { name = name.substring(pos + 1); } // 从zip 输入流中创建 目标文件 return makeFile(new File(dir, name), zf, ze); } // 定位目标实体的所在目录 private File locateDestDirectory(String path, File destDir) { File dir = destDir; int pos = path.indexOf('/'); while (pos > 0) { dir = new File(dir, path.substring(0, pos)); path = path.substring(pos + 1); pos = path.indexOf('/'); } return dir; } // private boolean makeFile(File file, ZipFile zf, ZipEntry ze) { OutputStream out = null; InputStream in = null; try { // boolean bool = file.exists() ? true : file.createNewFile(); // System.out.println("create New File:" + bool); if (!bool) { error = "createNewFile.Error,:-("; return false; } // out = new BufferedOutputStream(new FileOutputStream(file)); in = zf.getInputStream(ze); // long len = IOUtils.copy(in, out); // System.out.println("make New File length:" + len); return true; } catch (Exception e) { error = "makeFile.Error:(" + e.getLocalizedMessage() + ")"; return false; } finally { IOUtils.quietCloseOutputStream(out); IOUtils.quietCloseInputStream(in); } } }
参考资料:
解决Zip文件中文名问题 :
http://www.cnblogs.com/CUCmehp/archive/2008/10/28/1320872.html
加密,解密zip文件、对称加密,RSA,AES算法 :
http://hi.baidu.com/yezongbo/blog/item/1b7960fd6aae661308244d14.html
除了Java平台本身提供的API之外,我还发现一个开源的项目,Truezip (http://truezip.java.net/)有机会再研究吧。
附件是两个助手类文件,可下载使用(将.png后缀删除即可):
ZipHelper.java 、UnZipHelper.java