|
|
@@ -0,0 +1,297 @@
|
|
|
+package com.railway.common.utils;
|
|
|
+
|
|
|
+import com.railway.common.utils.file.FileUtils;
|
|
|
+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.io.InputStream;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.nio.charset.Charset;
|
|
|
+import java.util.Enumeration;
|
|
|
+import java.util.zip.CRC32;
|
|
|
+import java.util.zip.CheckedOutputStream;
|
|
|
+import java.util.zip.ZipEntry;
|
|
|
+import java.util.zip.ZipException;
|
|
|
+import java.util.zip.ZipFile;
|
|
|
+import java.util.zip.ZipOutputStream;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author ZhaoMn
|
|
|
+ */
|
|
|
+@SuppressWarnings("unchecked")
|
|
|
+@Slf4j
|
|
|
+public class ZipUtil {
|
|
|
+
|
|
|
+ final static String ZIP_FILE_SUFFIX = ".zip";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 文件打包
|
|
|
+ *
|
|
|
+ * @param filesPath 导出源文件目录
|
|
|
+ * @param zipPath zip文件保存目录
|
|
|
+ */
|
|
|
+ public static String zipExportFiles(String filesPath, String zipPath) throws ZipException {
|
|
|
+ File srcFilesPath = new File(filesPath);
|
|
|
+ return zipExportFiles(srcFilesPath, zipPath, srcFilesPath.getName());
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String zipExportFiles(String filesPath, String zipPath, String zipFileName)
|
|
|
+ throws ZipException {
|
|
|
+ File srcFilesPath = new File(filesPath);
|
|
|
+ return zipExportFiles(srcFilesPath, zipPath, zipFileName);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String zipExportFiles(File srcFilesPath, String zipPath, String zipFileName)
|
|
|
+ throws ZipException {
|
|
|
+ String fileName = zipFileName + ZIP_FILE_SUFFIX;
|
|
|
+ ZipUtil.zip(srcFilesPath.getAbsolutePath(), zipPath, fileName);
|
|
|
+ return fileName;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 递归压缩文件夹
|
|
|
+ *
|
|
|
+ * @param srcRootDir 压缩文件夹根目录的子路径
|
|
|
+ * @param file 当前递归压缩的文件或目录对象
|
|
|
+ * @param zos 压缩文件存储对象
|
|
|
+ */
|
|
|
+ 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(subPath);
|
|
|
+ zos.putNextEntry(entry);
|
|
|
+ try (InputStream is = new FileInputStream(file);
|
|
|
+ BufferedInputStream bis = new BufferedInputStream(is);) {
|
|
|
+ while ((count = bis.read(data, 0, bufferLen)) != -1) {
|
|
|
+ zos.write(data, 0, count);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ zos.closeEntry();
|
|
|
+ }
|
|
|
+ //如果是目录,则压缩整个目录
|
|
|
+ else {
|
|
|
+ //压缩目录中的文件或子目录
|
|
|
+ File[] childFileList = file.listFiles();
|
|
|
+ assert childFileList != null;
|
|
|
+ for (File file1 : childFileList) {
|
|
|
+ file1.getAbsolutePath().indexOf(file.getAbsolutePath());
|
|
|
+ zip(srcRootDir, file1, zos);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对文件或文件目录进行压缩
|
|
|
+ *
|
|
|
+ * @param srcPath 要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
|
|
|
+ * @param zipPath 压缩文件保存的路径。注意:zipPath不能是srcPath路径下的子文件夹
|
|
|
+ * @param zipFileName 压缩文件名
|
|
|
+ */
|
|
|
+ public static void zip(String srcPath, String zipPath, String zipFileName) throws ZipException {
|
|
|
+ log.info("begin to zip file {} ... to a {}/{} zip File...", srcPath, zipPath, zipFileName);
|
|
|
+ if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(zipPath) || StringUtils
|
|
|
+ .isEmpty(zipFileName)) {
|
|
|
+ log.error("parameter is null >>> srcPath : {},zipPath : {}, zipFileName : {}", srcPath,
|
|
|
+ zipPath, zipFileName);
|
|
|
+ throw new ZipException("压缩文件异常,参数为空!");
|
|
|
+ }
|
|
|
+
|
|
|
+ File srcFile = new File(srcPath);
|
|
|
+ //判断压缩文件保存的路径是否为源文件路径的子文件夹,如果是,则抛出异常(防止无限递归压缩的发生)
|
|
|
+ if (srcFile.isDirectory() && zipPath.contains(srcPath)) {
|
|
|
+ throw new ZipException("压缩文件保存的路径不能为源文件路径的子文件夹!");
|
|
|
+ }
|
|
|
+
|
|
|
+ //判断压缩文件保存的路径是否存在,如果不存在,则创建目录
|
|
|
+ File zipDir = new File(zipPath);
|
|
|
+ if (!zipDir.exists() || !zipDir.isDirectory()) {
|
|
|
+ zipDir.mkdirs();
|
|
|
+ }
|
|
|
+
|
|
|
+ //创建压缩文件保存的文件对象
|
|
|
+ String zipFilePath = zipPath + File.separator + zipFileName;
|
|
|
+ File zipFile = new File(zipFilePath);
|
|
|
+ // 删除已有文件
|
|
|
+ FileUtils.deleteFile(zipFilePath);
|
|
|
+
|
|
|
+ //如果只是压缩一个文件,则需要截取该文件的父目录
|
|
|
+ String srcRootDir = srcPath;
|
|
|
+ if (srcFile.isFile()) {
|
|
|
+ int index = srcPath.lastIndexOf(File.separator);
|
|
|
+ if (index != -1) {
|
|
|
+ srcRootDir = srcPath.substring(0, index);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ try (OutputStream os = new FileOutputStream(zipFile);
|
|
|
+ CheckedOutputStream cos = new CheckedOutputStream(os, new CRC32());
|
|
|
+ ZipOutputStream zos = new ZipOutputStream(cos);) {
|
|
|
+ //调用递归压缩方法进行目录或文件压缩
|
|
|
+ zip(srcRootDir, srcFile, zos);
|
|
|
+ zos.flush();
|
|
|
+ log.info("zip file " + zipFile.getAbsolutePath() + " has finished");
|
|
|
+ } catch (Exception e) {
|
|
|
+ if (zipFile.exists()) {
|
|
|
+ zipFile.delete();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ FileUtils.deleteDirectory(srcPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解压缩zip包
|
|
|
+ *
|
|
|
+ * @param zipFilePath zip文件的全路径
|
|
|
+ * @param unzipFilePath 解压后的文件保存的路径
|
|
|
+ * @param includeZipFileName 解压后的文件保存的路径是否包含压缩文件的文件名。true-包含;false-不包含
|
|
|
+ */
|
|
|
+ public static void unzip(String zipFilePath, String unzipFilePath, boolean includeZipFileName,
|
|
|
+ Charset charset) throws Exception {
|
|
|
+ if (StringUtils.isEmpty(zipFilePath) || StringUtils.isEmpty(unzipFilePath)) {
|
|
|
+ log.error("parameter is null >>> zipFilePath : {},unzipFilePath : {}", zipFilePath,
|
|
|
+ unzipFilePath);
|
|
|
+ throw new Exception("PARAMETER IS NULL!!!");
|
|
|
+ }
|
|
|
+ File zipFile = new File(zipFilePath);
|
|
|
+ //如果解压后的文件保存路径包含压缩文件的文件名,则追加该文件名到解压路径
|
|
|
+ if (includeZipFileName) {
|
|
|
+ String fileName = zipFile.getName();
|
|
|
+ if (!StringUtils.isEmpty(fileName)) {
|
|
|
+ fileName = fileName.substring(0, fileName.lastIndexOf("."));
|
|
|
+ }
|
|
|
+ unzipFilePath = unzipFilePath + File.separator + fileName;
|
|
|
+ }
|
|
|
+ //创建解压缩文件保存的路径
|
|
|
+ File unzipFileDir = new File(unzipFilePath);
|
|
|
+ if (!unzipFileDir.exists() || !unzipFileDir.isDirectory()) {
|
|
|
+ unzipFileDir.mkdirs();
|
|
|
+ }
|
|
|
+
|
|
|
+ //开始解压
|
|
|
+ ZipEntry entry;
|
|
|
+ String entryFilePath, entryDirPath;
|
|
|
+ File entryFile, entryDir;
|
|
|
+ int index, count, bufferSize = 1024;
|
|
|
+ byte[] buffer = new byte[bufferSize];
|
|
|
+
|
|
|
+ ZipFile zip;
|
|
|
+ try {
|
|
|
+ zip = new ZipFile(zipFile, charset);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new Exception("PARAMETER IS NULL!!!");
|
|
|
+ }
|
|
|
+ Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();
|
|
|
+ //循环对压缩包里的每一个文件进行解压
|
|
|
+ while (entries.hasMoreElements()) {
|
|
|
+ entry = entries.nextElement();
|
|
|
+ String entryName = entry.getName().replace("/", File.separator).replace("\\", File.separator);
|
|
|
+ //构建压缩包中一个文件解压后保存的文件全路径
|
|
|
+ entryFilePath = unzipFilePath + File.separator + entryName;
|
|
|
+ //构建解压后保存的文件夹路径
|
|
|
+ index = entryFilePath.lastIndexOf(File.separator);
|
|
|
+ if (index != -1) {
|
|
|
+ entryDirPath = entryFilePath.substring(0, index);
|
|
|
+ } else {
|
|
|
+ entryDirPath = "";
|
|
|
+ }
|
|
|
+ entryDir = new File(entryDirPath);
|
|
|
+ //如果文件夹路径不存在,则创建文件夹
|
|
|
+ if (!entryDir.exists() || !entryDir.isDirectory()) {
|
|
|
+ entryDir.mkdirs();
|
|
|
+ }
|
|
|
+
|
|
|
+ //创建解压文件
|
|
|
+ entryFile = new File(entryFilePath);
|
|
|
+ // 删除已有文件
|
|
|
+ FileUtils.deleteFile(entryFilePath);
|
|
|
+
|
|
|
+ //写入文件
|
|
|
+ try (OutputStream os = new FileOutputStream(entryFile);
|
|
|
+ BufferedOutputStream bos = new BufferedOutputStream(os);
|
|
|
+ InputStream is = zip.getInputStream(entry);
|
|
|
+ BufferedInputStream bis = new BufferedInputStream(is)) {
|
|
|
+ while ((count = bis.read(buffer, 0, bufferSize)) != -1) {
|
|
|
+ bos.write(buffer, 0, count);
|
|
|
+ }
|
|
|
+ bos.flush();
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ throw new Exception("File Not Found Exception!!!");
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new Exception("IO Exception!!!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ zip.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解压缩zip包
|
|
|
+ *
|
|
|
+ * @param zipFilePath zip文件的全路径
|
|
|
+ * @return 文件解压路径
|
|
|
+ */
|
|
|
+ public static String unzip(String zipFilePath) throws Exception {
|
|
|
+ // includeZipFileName 解压后的文件保存的路径是否包含压缩文件的文件名。true-包含;false-不包含
|
|
|
+ // 此处通过文件名获得解压路径,因此不需要再次包含文件名
|
|
|
+ String unzipFilePath = zipFilePath.substring(0, zipFilePath.lastIndexOf("."));
|
|
|
+ unzip(zipFilePath, unzipFilePath, false);
|
|
|
+ return unzipFilePath;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解压缩zip包
|
|
|
+ *
|
|
|
+ * @param zipFilePath zip文件的全路径
|
|
|
+ * @param unzipFilePath 解压后的文件保存的路径
|
|
|
+ */
|
|
|
+ public static void unzip(String zipFilePath, String unzipFilePath) throws Exception {
|
|
|
+ // includeZipFileName 解压后的文件保存的路径是否包含压缩文件的文件名。true-包含;false-不包含
|
|
|
+ boolean includeZipFileName = true;
|
|
|
+ Charset charset = Charset.forName("GBK");
|
|
|
+ unzip(zipFilePath, unzipFilePath, includeZipFileName, charset);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解压缩zip包
|
|
|
+ *
|
|
|
+ * @param zipFilePath zip文件的全路径
|
|
|
+ * @param unzipFilePath 解压后的文件保存的路径
|
|
|
+ */
|
|
|
+ public static void unzip(String zipFilePath, String unzipFilePath, Charset charset)
|
|
|
+ throws Exception {
|
|
|
+ // includeZipFileName 解压后的文件保存的路径是否包含压缩文件的文件名。true-包含;false-不包含
|
|
|
+ boolean includeZipFileName = true;
|
|
|
+ unzip(zipFilePath, unzipFilePath, includeZipFileName, charset);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解压缩zip包
|
|
|
+ *
|
|
|
+ * @param zipFilePath zip文件的全路径
|
|
|
+ * @param unzipFilePath 解压后的文件保存的路径
|
|
|
+ */
|
|
|
+ public static void unzip(String zipFilePath, String unzipFilePath, boolean includeZipFileName)
|
|
|
+ throws Exception {
|
|
|
+ Charset charset = Charset.forName("GBK");
|
|
|
+ unzip(zipFilePath, unzipFilePath, includeZipFileName, charset);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|