工具类取名ZIPUtil,规则:解压生成同名文件夹。压缩生成同名zip文件。
//解压,传入绝对路径
ZIPUtil.decompression("D://WangPan2.zip");
//压缩,传入绝对路径
ZIPUtil.compress("D://aaaa你.txt");
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.util.Enumeration;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.*;
/**
* 可以使用工具包zip4j
*/
public class ZIPUtil {
/**
* 解压zip压缩包
*
* @param zipFileAddress 压缩包路径,绝对路径
* @throws IOException
*/
public static void decompression(String zipFileAddress) throws ZipException {
Path zipFilePath = Paths.get(zipFileAddress);
if (!Files.exists(zipFilePath)) {
throw new ZipException("压缩包不存在:" + zipFileAddress);
}
//获取文件名称,去除掉后缀.zip
String rootDirName = zipFilePath.getFileName().toString().replaceAll("\\.zip$", "");
//生成解压路径,与压缩包同级目录下的同名文件夹
Path decompressionPath = zipFilePath.resolveSibling(rootDirName);
if (Files.exists(decompressionPath)) {
throw new ZipException("解压文件同名文件夹已存在");
}
try {
//读取压缩包,压缩包内有中文使用GBK才能让中文显示正确
ZipFile zipFile = new ZipFile(zipFilePath.toString(), Charset.forName("gbk"));
//压缩包内所有压缩文件目录
Enumeration extends ZipEntry> allEntries = zipFile.entries();
while (allEntries.hasMoreElements()) {
ZipEntry zipEntry = allEntries.nextElement();
System.out.println("解压文件目录:" + zipEntry.getName());
if (zipEntry.isDirectory()) {
//创建文件夹
Files.createDirectories(decompressionPath.resolve(zipEntry.getName()));
} else {
//压缩包内压缩文件解压路径
Path entrieFilePath = decompressionPath.resolve(zipEntry.getName());
//父路径不存在则创建父路径,按照压缩包目录生成规则,目录会比目录中文件优先生成,但是为了防止意外,增加目录判断
if (!Files.exists(entrieFilePath.getParent())) {
Files.createDirectories(entrieFilePath.getParent());
}
//创建解压文件
Files.createFile(entrieFilePath);
//输出流向输入流传数据。嵌套一层try用于自动关闭流。
try (BufferedInputStream i = new BufferedInputStream(zipFile.getInputStream(zipEntry));
BufferedOutputStream o = new BufferedOutputStream(new FileOutputStream(entrieFilePath.toString()));) {
byte[] b = new byte[1024];
int r;
while ((r = i.read(b, 0, b.length)) != -1) {
o.write(b, 0, r);
}
o.flush();
}
}
}
} catch (IOException e) {
e.printStackTrace();
throw new ZipException(e.getMessage());
}
}
/**
* 压缩文件或文件夹
*
* @param fileAddress 文件或文件夹的绝对地址
* @throws IOException
*/
public static void compress(String fileAddress) throws ZipException {
Path waitCompressPath = Paths.get(fileAddress);
//判断文件或文件夹是否存在
if (!Files.exists(waitCompressPath)) {
throw new ZipException("待压缩文件或文件夹不存在:" + fileAddress);
}
//判断是文件还是文件夹
if (Files.isDirectory(waitCompressPath)) {
//压缩文件夹
compressFolder(waitCompressPath);
} else {
//压缩文件
compressFile(waitCompressPath);
}
System.out.println("压缩完成,被压缩文件:" + fileAddress);
}
/**
* 压缩文件夹
*
* @param waitCompressFilePath 文件绝对地址
* @throws ZipException
*/
private static void compressFile(Path waitCompressFilePath) throws ZipException {
//解压文件名称,去除末尾的.xxx后缀
String removeSuffixFileName = waitCompressFilePath.getFileName().toString().replaceAll("\\.[^\\..]+$", "");
Path zipFilePath = waitCompressFilePath.resolveSibling(removeSuffixFileName + ".zip");
if (Files.exists(zipFilePath)) {
throw new ZipException("当前目录下,存在与需要压缩文件同名的.zip文件 :" + zipFilePath);
}
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(waitCompressFilePath.toFile())); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFilePath.toString())));) {
//创建压缩文件,上方在new FileOutputStream时会自动创建文件
// Files.createFile(zipFilePath);
//向zip中放入压缩文件
out.putNextEntry(new ZipEntry(waitCompressFilePath.getFileName().toString()));
//从输入流向输出流中读取数据
byte[] bytes = new byte[1024];
int read;
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
//关闭当前压缩文件
out.closeEntry();
} catch (IOException e) {
e.printStackTrace();
//未知io错误
throw new ZipException(e.getMessage());
}
}
/**
* 压缩文件夹
*
* @param waitCompressFilePath 文件夹绝对地址
* @throws ZipException
*/
private static void compressFolder(Path waitCompressFilePath) throws ZipException {
//创建同名压缩文件以.zip结尾
Path compressZipFilePath = waitCompressFilePath.resolveSibling(waitCompressFilePath.getFileName().toString() + ".zip");
if (Files.exists(compressZipFilePath)) {
throw new ZipException("压缩文件夹或文件同名.zip压缩包已存在。");
}
try (ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(compressZipFilePath.toString()));) {
//创建压缩文件,上方new FileOutputStream时会创建对应文件
// Files.createFile(compressZipFilePath);
//遍历文件夹,获取压缩条目
List zipEntries = ZIPUtil.getZipEntries(waitCompressFilePath);
for (Path zipEntryPath : zipEntries) {
//嵌套一层try确保流在任何时候都会被关闭
try (BufferedInputStream binput = new BufferedInputStream(new FileInputStream(waitCompressFilePath.resolve(zipEntryPath).toString()));) {
//输入流向输出流传数据
byte[] bytes = new byte[1024];
int read;
ZipEntry zipEntry = new ZipEntry(zipEntryPath.toString());
zipout.putNextEntry(zipEntry);
while ((read = binput.read(bytes, 0, bytes.length)) != -1) {
zipout.write(bytes, 0, read);
}
zipout.flush();
zipout.closeEntry();
}
}
} catch (IOException e) {
e.printStackTrace();
//未知io错误
throw new ZipException(e.getMessage());
}
}
/**
* 根据需要压缩的文件夹,生成zip总条目
*
* @param path 需要打zip包的文件夹绝对路径,如:D://WangPan
* @return 返回类型为列表,列表内path为相对于打文件夹的相对路径
* @throws IOException
*/
private static List getZipEntries(Path path) throws IOException {
// List collect = Files.walk(path).map(p -> path.relativize(p)).filter(p -> !"".equals(p.toString())).collect(Collectors.toList());
List collect = Files.walk(path).filter(p -> !Files.isDirectory(p)).map(p -> path.relativize(p)).collect(Collectors.toList());
return collect;
}
}