import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.CRC32; import java.util.zip.CheckedOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import com.hyb.constant.Constant; /** * <p> * 程序實現了ZIP壓縮[compression] * <p> * 大致功能包括用了多態,遞歸等JAVA核心技術,可以對單個文件和任意級聯文件夾進行壓縮和解壓。 需在代碼中自定義源輸入路徑和目標輸出路徑。 * <p> * 在本段代碼中,實現的是壓縮部分 */ public class ZipUtil { /** * @param zipFileName * 生成后得壓縮文件目錄 * @param inputFile * 要壓縮的目錄 * @throws Exception */ public static void zip(String zipFileName, File inputFile) throws Exception { Constant.LOGGER.info("壓縮中..."); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName)); BufferedOutputStream bo = new BufferedOutputStream(out); zip(out, inputFile, inputFile.getName(), bo); bo.close(); out.close(); // 輸出流關閉 Constant.LOGGER.info("壓縮完成"); } public static void zip(ZipOutputStream out, File f, String base, BufferedOutputStream bo) throws Exception { // 方法重載 if (f.isDirectory()) { File[] fl = f.listFiles(); if (fl.length == 0) { out.putNextEntry(new ZipEntry(base + "/")); // 創建zip壓縮進入點base Constant.LOGGER.info(base + "/"); } for (int i = 0; i < fl.length; i++) { zip(out, fl[i], base + "/" + fl[i].getName(), bo); // 遞歸遍歷子文件夾 } } else { out.putNextEntry(new ZipEntry(base)); // 創建zip壓縮進入點base Constant.LOGGER.info(base); FileInputStream in = new FileInputStream(f); BufferedInputStream bi = new BufferedInputStream(in); int b; while ((b = bi.read()) != -1) { bo.write(b); // 將字節流寫入當前zip目錄 } bi.close(); in.close(); // 輸入流關閉 } } public static void zip(String srcPath, String zipPath, String zipFileName) throws Exception { CheckedOutputStream cos = null; ZipOutputStream zos = null; try { File srcFile = new File(srcPath); // 判斷壓縮文件保存的路徑是否為源文件路徑的子文件夾,如果是,則拋出異常(防止無限遞歸壓縮的發生) if (srcFile.isDirectory() && zipPath.indexOf(srcPath) != -1) { throw new Exception("壓縮文件保存的路徑是否為源文件路徑的子文件夾"); } // 判斷壓縮文件保存的路徑是否存在,如果不存在,則創建目錄 File zipDir = new File(zipPath); if (!zipDir.exists() || !zipDir.isDirectory()) { zipDir.mkdirs(); } // 創建壓縮文件保存的文件對象 String zipFilePath = zipPath + File.separator + zipFileName; File zipFile = new File(zipFilePath); cos = new CheckedOutputStream(new FileOutputStream(zipFile), new CRC32()); zos = new ZipOutputStream(cos); // 如果只是壓縮一個文件,則需要截取該文件的父目錄 String srcRootDir = srcPath; if (srcFile.isFile()) { int index = srcPath.lastIndexOf(File.separator); if (index != -1) { srcRootDir = srcPath.substring(0, index); } } // 調用遞歸壓縮方法進行目錄或文件壓縮 zip(srcRootDir, srcFile, zos); zos.flush(); } catch (Exception e) { throw e; } finally { try { if (zos != null) { zos.close(); } } catch (Exception e) { e.printStackTrace(); } } } private static void zip(String srcRootDir, File file, ZipOutputStream zos) throws Exception { if (file == null) { return; } // 如果是文件,則直接壓縮該文件 if (file.isFile()) { int count, bufferLen = 1024; byte data[] = new byte[bufferLen]; // 獲取文件相對於壓縮文件夾根目錄的子路徑 // String subPath = file.getAbsolutePath(); // int index = subPath.indexOf(srcRootDir); // if (index != -1) { // subPath = subPath.substring(srcRootDir.length() + File.separator.length()); // } ZipEntry entry = new ZipEntry(file.getName()); zos.putNextEntry(entry); BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); while ((count = bis.read(data, 0, bufferLen)) != -1) { zos.write(data, 0, count); } bis.close(); zos.closeEntry(); } // 如果是目錄,則壓縮整個目錄 else { // 壓縮目錄中的文件或子目錄 File[] childFileList = file.listFiles(); for (int n = 0; n < childFileList.length; n++) { childFileList[n].getAbsolutePath().indexOf(file.getAbsolutePath()); zip(srcRootDir, childFileList[n], zos); } } } public static void unzip(String zipPath, String targetPath) { long startTime=System.currentTimeMillis(); try { ZipInputStream zin=new ZipInputStream(new FileInputStream(zipPath));//輸入源zip路徑 BufferedInputStream bin=new BufferedInputStream(zin); File Fout=null; ZipEntry entry; try { while((entry = zin.getNextEntry())!=null && !entry.isDirectory()){ Fout=new File(targetPath,entry.getName()); if(!Fout.exists()){ (new File(Fout.getParent())).mkdirs(); } FileOutputStream out=new FileOutputStream(Fout); BufferedOutputStream Bout=new BufferedOutputStream(out); int b; while((b=bin.read())!=-1){ Bout.write(b); } Bout.close(); out.close(); Constant.LOGGER.info(Fout+"解壓成功"); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (bin != null) { bin.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (zin != null) { zin.close(); } } catch (IOException e) { e.printStackTrace(); } } } catch (FileNotFoundException e) { e.printStackTrace(); } long endTime=System.currentTimeMillis(); Constant.LOGGER.info("耗費時間: "+(endTime-startTime)+" ms"); } /** * 測試 * * @param args */ public static void main(String[] args) { try { // ZipUtil.zip("G:\\a.zip", new File("G:\\a")); unzip("G:\\a.zip", "G:\\a"); } catch (Exception e) { e.printStackTrace(); } } }
