package com.yanzuoguang.util.helper; import com.yanzuoguang.util.YzgError; import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; /** * ZIP压缩处理工具类 * * @author 颜佐光 */ public class ZipHelper { /** * @param dirFile * @param zipFile * @param isDir 是否显示最下级相对目录 * @throws IOException * @创建日期:2018年5月4日 下午3:07:55 * @作者: meter * @描述:压缩指定目录下所有文件 * @Title: zipDirectory */ public static void zipDirectory(File dirFile, File zipFile, boolean isDir) throws IOException { if (dirFile == null) { throw YzgError.getRuntimeException("018"); } if (!dirFile.isDirectory()) { throw YzgError.getRuntimeException("019", dirFile.getName()); } if (zipFile == null) { zipFile = new File(dirFile.getAbsolutePath() + ".zip"); } String dirName = StringHelper.EMPTY; if (isDir) { dirName = dirFile.getName() + File.separator; } // 创建zip输出流 ZipOutputStream zipOutStream = new ZipOutputStream(new FileOutputStream(zipFile), StandardCharsets.UTF_8); try { // 创建缓冲输出流 BufferedOutputStream bufferOutStream = new BufferedOutputStream(zipOutStream); try { dealDirFile(dirFile, dirName, bufferOutStream, zipOutStream); } finally { //最后关闭输出流 bufferOutStream.close(); } } finally { zipOutStream.close(); } } /** * @param dirFile * @param zipFile * @throws IOException * @创建日期:2018年5月4日 下午3:07:55 * @作者: meter * @描述:压缩指定目录下所有文件 * @Title: zipDirectory */ public static void zipDirectory(File dirFile, File zipFile) throws IOException { zipDirectory(dirFile, zipFile, false); } /** * 讲文件添加到新目录,并且添加一个新文件 * * @param zipTo 目标ZIP * @param zipFrom 来源ZIP * @param sourcePath 下载路径 * @param sourceFiles 需要添加的文件 * @throws Exception */ public static void zipTo(File zipTo, File zipFrom, String sourcePath, File... sourceFiles) throws IOException { // 创建zip输出流 ZipOutputStream zipOutStream = new ZipOutputStream(new FileOutputStream(zipTo), StandardCharsets.UTF_8); try { // 创建缓冲输出流 BufferedOutputStream bufferOutStream = new BufferedOutputStream(zipOutStream); try { copyZip(zipFrom, zipOutStream, bufferOutStream, getExpand(sourcePath, sourceFiles)); for (File sourceFile : sourceFiles) { zipFile(sourcePath, sourceFile, zipOutStream, bufferOutStream); } } finally { //最后关闭输出流 bufferOutStream.close(); } } finally { zipOutStream.close(); } } /** * 讲文件添加到新目录,并且添加一个新文件 * * @param zipTo 目标ZIP * @param sourcePath 下载路径 * @param sourceFiles 需要添加的文件 * @throws Exception */ public static void zip(File zipTo, String sourcePath, File... sourceFiles) throws IOException { System.out.println("待压缩文件:" + zipTo.getAbsolutePath()); boolean exints = zipTo.exists(); // 添加到已经存在的压缩文件中 File tempFile = new File(zipTo.getAbsolutePath() + ".tmp"); // 创建zip输出流 ZipOutputStream zipOutStream; if (exints) { // 创建临时压缩文件 zipOutStream = new ZipOutputStream(new FileOutputStream(tempFile), StandardCharsets.UTF_8); } else { // 新创建压缩文件 zipOutStream = new ZipOutputStream(new FileOutputStream(zipTo), StandardCharsets.UTF_8); } try { // 创建缓冲输出流 BufferedOutputStream bufferOutStream = new BufferedOutputStream(zipOutStream); try { if (exints) { copyZip(zipTo, zipOutStream, bufferOutStream, getExpand(sourcePath, sourceFiles)); } for (File sourceFile : sourceFiles) { zipFile(sourcePath, sourceFile, zipOutStream, bufferOutStream); } } finally { //最后关闭输出流 bufferOutStream.close(); } } finally { zipOutStream.close(); } // 假如存在,则删除临时文件,并更改临时文件名称 if (tempFile.exists()) { boolean flag = zipTo.delete(); if (flag) { tempFile.renameTo(zipTo); } else { throw YzgError.getRuntimeException("020", tempFile.getName()); } } } /** * 获取需要排除的文件名和文件路径 * * @param sourcePath 文件路径 * @param sourceFiles 文件名 * @return */ private static List<String> getExpand(String sourcePath, File[] sourceFiles) { List<String> ret = new ArrayList<>(); for (File sourceFile : sourceFiles) { ret.add(sourcePath + sourceFile.getName()); } return ret; } /** * 讲压缩文件保存到另外一个压缩文件 * * @param fromFile 来源文件 * @param zipOutStream 目标文件 * @param bufferOutStream 目标文件流 * @param expandFiles 需要排除的文件 * @throws IOException */ private static void copyZip(File fromFile, ZipOutputStream zipOutStream, BufferedOutputStream bufferOutStream, List<String> expandFiles) throws IOException { ZipFile fromZipFile = new ZipFile(fromFile); Enumeration<? extends ZipEntry> fromEntries = fromZipFile.entries(); while (fromEntries.hasMoreElements()) { ZipEntry fromEntry = fromEntries.nextElement(); if (expandFiles.indexOf(fromEntry.getName()) > -1) { continue; } zipOutStream.putNextEntry(new ZipEntry(fromEntry.getName())); if (!fromEntry.isDirectory()) { write(fromZipFile.getInputStream(fromEntry), bufferOutStream); } zipOutStream.closeEntry(); } fromZipFile.close(); } /** * 执行文件压缩 * * @param file 需要压缩的文件 * @param zipOutStream 目标文件 * @param bufferOutStream 目标文件流 * @throws IOException */ private static void zipFile(String sourcePath, File file, ZipOutputStream zipOutStream, BufferedOutputStream bufferOutStream) throws IOException { if (!file.exists()) { throw YzgError.getRuntimeException("021", file.getAbsolutePath()); } // 创建压缩文件实体 ZipEntry entry = new ZipEntry(sourcePath + file.getName()); // 添加实体 zipOutStream.putNextEntry(entry); // 创建输入流 BufferedInputStream bufferInputStream = new BufferedInputStream(new FileInputStream(file)); write(bufferInputStream, bufferOutStream); zipOutStream.closeEntry(); } /** * @param inputStream * @param outStream * @throws IOException * @创建日期:2018年5月4日 下午2:09:37 * @作者: meter * @描述:读写zip文件 * @Title: write */ private static void write(InputStream inputStream, OutputStream outStream) throws IOException { try { byte[] data = new byte[4096]; int length = 0; while ((length = inputStream.read(data)) != -1) { outStream.write(data, 0, length); } outStream.flush();//刷新输出流 } finally { inputStream.close();//关闭输入流 } } /** * @param dirFile * @param parentDir * @param bufferOutStream * @param zipOutStream * @throws IOException * @创建日期:2018年5月4日 下午4:38:46 * @作者: meter * @描述:处理目录文件 * @Title: dealDirFile */ private static void dealDirFile(File dirFile, String parentDir, BufferedOutputStream bufferOutStream, ZipOutputStream zipOutStream) throws IOException { File[] fileList = dirFile.listFiles(); if (fileList == null) { return; } for (File file : fileList) { if (file.isFile()) { // 创建压缩文件实体 ZipEntry entry = new ZipEntry(parentDir + file.getName()); // 添加实体 zipOutStream.putNextEntry(entry); // 创建输入流 BufferedInputStream bufferInputStream = new BufferedInputStream(new FileInputStream(file)); write(bufferInputStream, bufferOutStream); } else { dealDirFile(file, parentDir + file.getName() + File.separator, bufferOutStream, zipOutStream); } } } /** * @param dirPath * @param zipPath * @throws IOException * @创建日期:2018年5月4日 下午3:22:11 * @作者: meter * @描述:重载zipDirectory * @Title: zipDirectory */ public static void zipDirectory(String dirPath, String zipPath) throws IOException { if (zipPath == null || "".equals(zipPath)) { zipDirectory(new File(dirPath), null); } else { zipDirectory(new File(dirPath), new File(zipPath)); } } //------------------------------------------------米特华丽的分割线---------------------------------------------------------------------------------------- /** * @param zipFile * @param destDir * @throws IOException * @创建日期:2018年5月4日 下午4:00:41 * @作者: meter * @描述:解压文件 * @Title: unzip */ public static void unzip(File zipFile, File destDir) throws IOException { ZipFile zipOutFile = new ZipFile(zipFile, Charset.forName("gbk")); Enumeration<? extends ZipEntry> entries = zipOutFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); if (entry.isDirectory()) { File tempFile = new File(destDir.getAbsolutePath() + File.separator + entry.getName()); if (!tempFile.exists()) { tempFile.mkdirs(); } } else { File tempFile = new File(destDir.getAbsolutePath() + File.separator + entry.getName()); checkParentDir(tempFile); FileOutputStream fileOutStream = new FileOutputStream(tempFile); BufferedOutputStream bufferOutStream = new BufferedOutputStream(fileOutStream); write(zipOutFile.getInputStream(entry), bufferOutStream); bufferOutStream.close(); fileOutStream.close(); } } zipOutFile.close();//记得关闭zip文件 } /** * @param file * @创建日期:2018年5月4日 下午4:37:41 * @作者: meter * @描述:验证父目录是否存在,否则创建 * @Title: checkParentDir */ private static void checkParentDir(File file) { if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } } }