-
压缩文件或文件夹(包括所有子目录文件)
-
@param sourceFile 源文件
-
@param format 格式(zip或rar)
-
@throws IOException 异常信息
*/
public static void zipFileTree(File sourceFile, String format) throws IOException {
ZipOutputStream zipOutputStream = null;
try {
String zipFileName;
if (sourceFile.isDirectory()) { // 目录
zipFileName = sourceFile.getParent() + File.separator + sourceFile.getName() + “.”
- format;
} else { // 单个文件
zipFileName = sourceFile.getParent()
-
sourceFile.getName().substring(0, sourceFile.getName().lastIndexOf(“.”))
-
“.” + format;
}
// 压缩输出流
zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
zip(sourceFile, zipOutputStream, “”);
} finally {
if (null != zipOutputStream) {
// 关闭流
try {
zipOutputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
/**
-
递归压缩文件
-
@param file 当前文件
-
@param zipOutputStream 压缩输出流
-
@param relativePath 相对路径
-
@throws IOException IO异常
*/
private static void zip(File file, ZipOutputStream zipOutputStream, String relativePath)
throws IOException {
FileInputStream fileInputStream = null;
try {
if (file.isDirectory()) { // 当前为文件夹
// 当前文件夹下的所有文件
File[] list = file.listFiles();
if (null != list) {
// 计算当前的相对路径
relativePath += (relativePath.length() == 0 ? “” : “/”) + file.getName();
// 递归压缩每个文件
for (File f : list) {
zip(f, zipOutputStream, relativePath);
}
}
} else { // 压缩文件
// 计算文件的相对路径
relativePath += (relativePath.length() == 0 ? “” : “/”) + file.getName();
// 写入单个文件
zipOutputStream.putNextEntry(new ZipEntry(relativePath));
fileInputStream = new FileInputStream(file);
int readLen;
byte[] buffer = new byte[1024];
while ((readLen = fileInputStream.read(buffer)) != -1) {
zipOutputStream.write(buffer, 0, readLen);
}
zipOutputStream.closeEntry();
}
} finally {
// 关闭流
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception {
String path = “D:/test”;
String format = “zip”;
zipFileTree(new File(path), format);
}
}
上例将test目录下的所有文件压缩到同一目录下的test.zip文件中。
还有一种更简单的方式,我们不自己写递归遍历。借助Java原生类,SimpleFileVisitor,它提供了几个访问文件的方法,其中有个方法visitFile,对于文件树中的每一个文件(文件夹除外),都会调用这个方法。我们只要写一个类继承SimpleFileVisitor,然后重写visitFile方法,实现将每一个文件写入到压缩文件中即可。
当然,除了visitFile方法,它里面还有preVisitDirectory,postVisitDirectory,visitFileFailed等方法,通过方法名大家也猜出什么意思了。
package com.nobody.zip;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
-
@Description
-
@Author Mr.nobody
-
@Date 2021/3/8
-
@Version 1.0.0
*/
public class ZipFileTree extends SimpleFileVisitor
// zip输出流
private ZipOutputStream zipOutputStream;
// 源目录
private Path sourcePath;
public ZipFileTree() {}
/**
-
压缩目录以及所有子目录文件
-
@param sourceDir 源目录
*/
public void zipFile(String sourceDir) throws IOException {
try {
// 压缩后的文件和源目录在同一目录下
String zipFileName = sourceDir + “.zip”;
this.zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
this.sourcePath = Paths.get(sourceDir);
// 开始遍历文件树
Files.walkFileTree(sourcePath, this);
} finally {
// 关闭流
if (null != zipOutputStream) {
zipOutputStream.close();
}
}
}
// 遍历到的每一个文件都会执行此方法
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
// 取相对路径
Path targetFile = sourcePath.relativize(file);
// 写入单个文件
zipOutputStream.putNextEntry(new ZipEntry(targetFile.toString()));
byte[] bytes = Files.readAllBytes(file);
zipOutputStream.write(bytes, 0, bytes.length);
zipOutputStream.closeEntry();
// 继续遍历
return FileVisitResult.CONTINUE;
}
// 遍历每一个目录时都会调用的方法
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException {
return super.preVisitDirectory(dir, attrs);
}
// 遍历完一个目录下的所有文件后,再调用这个目录的方法
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
return super.postVisitDirectory(dir, exc);
}
// 遍历文件失败后调用的方法
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return super.visitFileFailed(file, exc);
}
public static void main(String[] args) throws IOException {
// 需要压缩源目录
String sourceDir = “D:/test”;
// 压缩
new ZipFileTree().zipFile(sourceDir);
}
}
=================================================================
解压压缩包,借助ZipInputStream类,可以读取到压缩包中的每一个文件,然后根据读取到的文件属性,写入到相应路径下即可。对于解压压缩包中是文件树的结构,每读取到一个文件后,如果是多层路径下的文件,需要先创建父目录,再写入文件流。
package com.nobody.zip;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
-
@Description 解压缩文件工具类
-
@Author Mr.nobody
-
@Date 2021/3/8
-
@Version 1.0.0
*/
public class ZipUtils {
/**
-
解压
-
@param zipFilePath 带解压文件
-
@param desDirectory 解压到的目录
-
@throws Exception
*/
public static void unzip(String zipFilePath, String desDirectory) throws Exception {
File desDir = new File(desDirectory);
if (!desDir.exists()) {
boolean mkdirSuccess = desDir.mkdir();
if (!mkdirSuccess) {
throw new Exception(“创建解压目标文件夹失败”);
}
}
// 读入流
ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath));
// 遍历每一个文件
ZipEntry zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
if (zipEntry.isDirectory()) { // 文件夹
String unzipFilePath = desDirectory + File.separator + zipEntry.getName();
// 直接创建
mkdir(new File(unzipFilePath));
} else { // 文件
String unzipFilePath = desDirectory + File.separator + zipEntry.getName();
File file = new File(unzipFilePath);
// 创建父目录
mkdir(file.getParentFile());
// 写出文件流
BufferedOutputStream bufferedOutputStream =
new BufferedOutputStream(new FileOutputStream(unzipFilePath));
byte[] bytes = new byte[1024];
int readLen;
while ((readLen = zipInputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes, 0, readLen);
}
bufferedOutputStream.close();
}
zipInputStream.closeEntry();
zipEntry = zipInputStream.getNextEntry();
}
zipInputStream.close();
}
// 如果父目录不存在则创建
private static void mkdir(File file) {
if (null == file || file.exists()) {
return;
}
mkdir(file.getParentFile());
最后
![腾讯T3大牛总结的500页MySQL实战笔记意外爆火,P8看了直呼内行](https://upload-images.jianshu.io/upload_
必看视频!获取2024年最新Java开发全套学习资料 备注Java
images/24616006-834b2134bb3993f8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
file.exists()) {
return;
}
mkdir(file.getParentFile());
最后
[外链图片转存中…(img-ulbEU20E-1716459388519)]
![腾讯T3大牛总结的500页MySQL实战笔记意外爆火,P8看了直呼内行](https://upload-images.jianshu.io/upload_
必看视频!获取2024年最新Java开发全套学习资料 备注Java
images/24616006-834b2134bb3993f8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)