package com.gec.it.excel.write;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.zip.*;
/**
* @Author Miracle xyt
* @Date 2024/7/10 17:12
* @Version 1.0
*/
public class ZipUtils {
/**
* 解压文件
*
* @param file 压缩文件
* @param targetDir 解压文件输出的目录
* @throws IOException
*/
public static void unPacket(Path file, Path targetDir) throws IOException {
if (!Files.exists(targetDir)) {
Files.createDirectories(targetDir);
}
// 创建zip对象
ZipFile zipFile = new ZipFile(file.toFile());
try {
// 读取zip流
try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(file), Charset.forName("GBK"))) {
ZipEntry zipEntry = null;
// 遍历每一个zip项
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
// 获取zip项目名称
String entryName = zipEntry.getName();
// 构建绝对路径
Path entryFile = targetDir.resolve(entryName);
if (zipEntry.isDirectory()) { // 文件夹
if (!Files.isDirectory(entryFile)) {
Files.createDirectories(entryFile);
}
} else { // 文件
// 读取zip项数据流
try (InputStream zipEntryInputStream = zipFile.getInputStream(zipEntry)) {
try (OutputStream fileOutputStream = Files.newOutputStream(entryFile, StandardOpenOption.CREATE_NEW)) {
byte[] buffer = new byte[4096];
int length = 0;
while ((length = zipEntryInputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, length);
}
fileOutputStream.flush();
}
}
}
}
}
} finally {
zipFile.close();
}
}
/**
* 压缩指定的文件
*
* @param files 目标文件
* @param zipFile 生成的压缩文件
* @throws IOException
*/
public static void packet(Path[] files, Path zipFile) throws IOException {
OutputStream outputStream = Files.newOutputStream(zipFile, StandardOpenOption.CREATE);
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
try {
for (Path file : files) {
if (Files.isDirectory(file)) {
continue;
}
try (InputStream inputStream = Files.newInputStream(file)) {
// 创建一个压缩项,指定名称
ZipEntry zipEntry = new ZipEntry(file.getFileName().toString());
// 添加到压缩流
zipOutputStream.putNextEntry(zipEntry);
// 写入数据
int len = 0;
byte[] buffer = new byte[1024 * 10];
while ((len = inputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
zipOutputStream.flush();
}
}
// 完成所有压缩项的添加
zipOutputStream.closeEntry();
} finally {
zipOutputStream.close();
outputStream.close();
}
}
/**
* 压缩指定的目录
*
* @param folder
* @param zipFile
* @throws IOException
*/
public static void packet(Path folder, Path zipFile) throws IOException {
if (!Files.isDirectory(folder)) {
throw new IllegalArgumentException(folder.toString() + " 不是合法的文件夹");
}
OutputStream outputStream = Files.newOutputStream(zipFile, StandardOpenOption.CREATE);
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
LinkedList<String> path = new LinkedList<>();
try {
Files.walkFileTree(folder, new FileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
if (Files.isDirectory(folder)) {
// 开始遍历目录
String folder = dir.getFileName().toString();
path.addLast(folder);
// 写入目录
ZipEntry zipEntry = new ZipEntry(path.stream().collect(Collectors.joining("/", "", "/")));
try {
zipOutputStream.putNextEntry(zipEntry);
zipOutputStream.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
// 开始遍历文件
try (InputStream inputStream = Files.newInputStream(file)) {
// 创建一个压缩项,指定名称
String fileName = path.size() > 0
? path.stream().collect(Collectors.joining("/", "", "")) + "/" + file.getFileName().toString()
: file.getFileName().toString();
ZipEntry zipEntry = new ZipEntry(fileName);
// 添加到压缩流
zipOutputStream.putNextEntry(zipEntry);
// 写入数据
int len = 0;
byte[] buffer = new byte[1024 * 10];
while ((len = inputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
zipOutputStream.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
// 结束遍历目录
if (!path.isEmpty()) {
path.removeLast();
}
return FileVisitResult.CONTINUE;
}
});
zipOutputStream.closeEntry();
} finally {
zipOutputStream.close();
outputStream.close();
}
}
public static boolean isEmpty(String str) {
return (str == null || "".equals(str));
}
/**
* 递归压缩文件夹
*
* @param srcRootDir 压缩文件夹根目录的子路径
* @param file 当前递归压缩的文件或目录对象
* @param zos 压缩文件存储对象
* @throws Exception
*/
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);
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);
}
}
}
/**
* 对文件或文件目录进行压缩
*
* @param srcPath 要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
* @param zipPath 压缩文件保存的路径。注意:zipPath不能是srcPath路径下的子文件夹
* @param zipFileName 压缩文件名
* @throws Exception
*/
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) {
return;
}
//判断压缩文件保存的路径是否存在,如果不存在,则创建目录
File zipDir = new File(zipPath);
if (!zipDir.exists() || !zipDir.isDirectory()) {
zipDir.mkdirs();
}
//创建压缩文件保存的文件对象
String zipFilePath = zipPath + File.separator + zipFileName;
File zipFile = new File(zipFilePath);
if (zipFile.exists()) {
//检测文件是否允许删除,如果不允许删除,将会抛出SecurityException
SecurityManager securityManager = new SecurityManager();
securityManager.checkDelete(zipFilePath);
//删除已存在的目标文件
zipFile.delete();
}
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();
}
}
}
/**
* 解压缩zip包
*
* @param zipFilePath zip文件的全路径
* @param unzipFilePath 解压后的文件保存的路径
* @param includeZipFileName 解压后的文件保存的路径是否包含压缩文件的文件名。true-包含;false-不包含
*/
public static boolean unZip(String zipFilePath, String unzipFilePath, boolean includeZipFileName) {
initOS();
if (isEmpty(zipFilePath) || isEmpty(unzipFilePath)) {
return false;
}
File zipFile = new File(zipFilePath);
//如果解压后的文件保存路径包含压缩文件的文件名,则追加该文件名到解压路径
if (includeZipFileName) {
String fileName = zipFile.getName();
if (!isEmpty(fileName)) {
fileName = fileName.substring(0, fileName.lastIndexOf("."));
}
unzipFilePath = unzipFilePath + dir_p + fileName;
}
//创建解压缩文件保存的路径
File unzipFileDir = new File(unzipFilePath);
if ((!unzipFileDir.exists() || !unzipFileDir.isDirectory()) && !unzipFileDir.mkdirs()) {
return false;
}
//开始解压
ZipEntry entry;
String entryFilePath;
String entryDirPath;
File entryFile;
File entryDir;
int index = 0;
int count = 0;
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
ZipFile zip;
try {
zip = new ZipFile(zipFile, ZipFile.OPEN_READ, Charset.forName("GBK"));
} catch (IOException e) {
return false;
}
Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();
//循环对压缩包里的每一个文件进行解压
while (entries.hasMoreElements()) {
entry = entries.nextElement();
//构建压缩包中一个文件解压后保存的文件全路径
String entryName = entry.getName();
entryFilePath = unzipFilePath + dir_p + entryName;
//构建解压后保存的文件夹路径
if (entryName.contains("\\") || entryName.contains("/")) {
int index1 = entryFilePath.substring(0, entryFilePath.length() - 2).lastIndexOf("\\");
int index2 = entryFilePath.substring(0, entryFilePath.length() - 2).lastIndexOf("/");
if (index1 < index2) {
index = index2;
} else {
index = index1;
}
} else {
int index1 = entryFilePath.lastIndexOf("\\");
int index2 = entryFilePath.lastIndexOf("/");
if (index1 < index2) {
index = index2;
} else {
index = index1;
}
}
//获得解压文件上层目录
if (index != -1) {
entryDirPath = entryFilePath.substring(0, index);
} else {
entryDirPath = "";
}
// 创建解压文件上层目录
entryDir = new File(entryDirPath);
if ((!entryDir.exists() || !entryDir.isDirectory()) && !entryDir.mkdirs()) {
return false;
}
//创建解压文件
entryFile = new File(entryFilePath);
if (entryFile.exists() && entryFile.isFile()) {
//删除已存在的目标文件
if (!entryFile.delete()) {
}
}
if (!entry.isDirectory()) {
//写入文件
try {
bos = new BufferedOutputStream(new FileOutputStream(entryFile));
bis = new BufferedInputStream(zip.getInputStream(entry));
while ((count = bis.read(buffer, 0, bufferSize)) != -1) {
bos.write(buffer, 0, count);
}
bos.flush();
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
try {
if (bos != null) {
bos.flush();
}
if (bos != null) {
bos.close();
bos = null;
}
if (bis != null) {
bis.close();
bis = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
} else if (!entryFile.mkdirs()) {
break;
}
}//while
if (zip != null) {
try {
zip.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return true;
}
/**
* 初始化系统相关信息
*/
private static void initOS() {
Properties properties = System.getProperties();
String osName = properties.getProperty("os.name");
if (!isEmpty(osName)) {
osName = osName.toLowerCase();
if (osName.contains("windows")) {
dir_p = "\\";
} else {
dir_p = "/";
}
} else {
dir_p = "/";
}
}
private static String dir_p;
public static void main(String[] args) throws Exception {
String unzipFilePath = "D:\\AXYTWorkRecord\\Android\\生产环境全量备份.zip";
String unzipiTargetDir = "D:\\AXYTWorkRecord\\CD2000";
ZipUtils.unZip(unzipFilePath, unzipiTargetDir, true);
}
}
用Java实现在Windows/Linux环境,压缩文件和解压文件 zip格式
于 2024-07-10 17:57:13 首次发布