mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
add zip append
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
# 5.7.15 (2021-10-20)
|
# 5.7.15 (2021-10-21)
|
||||||
|
|
||||||
### 🐣新特性
|
### 🐣新特性
|
||||||
* 【db 】 Db.quietSetAutoCommit增加判空(issue#I4D75B@Gitee)
|
* 【db 】 Db.quietSetAutoCommit增加判空(issue#I4D75B@Gitee)
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
* 【core 】 ContentType增加build重载(pr#1898@Github)
|
* 【core 】 ContentType增加build重载(pr#1898@Github)
|
||||||
* 【bom 】 支持scope=import方式引入(issue#1561@Github)
|
* 【bom 】 支持scope=import方式引入(issue#1561@Github)
|
||||||
* 【core 】 新增Hash接口,HashXXX继承此接口
|
* 【core 】 新增Hash接口,HashXXX继承此接口
|
||||||
|
* 【core 】 ZipUtil增加append方法(pr#441@Gitee)
|
||||||
|
|
||||||
### 🐞Bug修复
|
### 🐞Bug修复
|
||||||
* 【core 】 修复CollUtil.isEqualList两个null返回错误问题(issue#1885@Github)
|
* 【core 】 修复CollUtil.isEqualList两个null返回错误问题(issue#1885@Github)
|
||||||
|
@@ -0,0 +1,84 @@
|
|||||||
|
package cn.hutool.core.compress;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.CopyOption;
|
||||||
|
import java.nio.file.FileAlreadyExistsException;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.FileVisitResult;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.SimpleFileVisitor;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zip文件拷贝的FileVisitor实现,zip中追加文件,此类非线程安全<br>
|
||||||
|
* 此类在遍历源目录并复制过程中会自动创建目标目录中不存在的上级目录。
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 5.7.15
|
||||||
|
*/
|
||||||
|
public class ZipCopyVisitor extends SimpleFileVisitor<Path> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 源Path,或基准路径,用于计算被拷贝文件的相对路径
|
||||||
|
*/
|
||||||
|
private final Path source;
|
||||||
|
private final FileSystem fileSystem;
|
||||||
|
private final CopyOption[] copyOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param source 源Path,或基准路径,用于计算被拷贝文件的相对路径
|
||||||
|
* @param fileSystem 目标Zip文件
|
||||||
|
* @param copyOptions 拷贝选项,如跳过已存在等
|
||||||
|
*/
|
||||||
|
public ZipCopyVisitor(Path source, FileSystem fileSystem, CopyOption... copyOptions) {
|
||||||
|
this.source = source;
|
||||||
|
this.fileSystem = fileSystem;
|
||||||
|
this.copyOptions = copyOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||||
|
final Path targetDir = resolveTarget(dir);
|
||||||
|
if(StrUtil.isNotEmpty(targetDir.toString())){
|
||||||
|
// 在目标的Zip文件中的相对位置创建目录
|
||||||
|
try {
|
||||||
|
Files.copy(dir, targetDir, copyOptions);
|
||||||
|
} catch (FileAlreadyExistsException e) {
|
||||||
|
if (false == Files.isDirectory(targetDir)) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
|
// 如果目标存在,无论目录还是文件都抛出FileAlreadyExistsException异常,此处不做特别处理
|
||||||
|
Files.copy(file, resolveTarget(file), copyOptions);
|
||||||
|
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据源文件或目录路径,拼接生成目标的文件或目录路径<br>
|
||||||
|
* 原理是首先截取源路径,得到相对路径,再和目标路径拼接
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 如:源路径是 /opt/test/,需要拷贝的文件是 /opt/test/a/a.txt,得到相对路径 a/a.txt<br>
|
||||||
|
* 目标路径是/home/,则得到最终目标路径是 /home/a/a.txt
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param file 需要拷贝的文件或目录Path
|
||||||
|
* @return 目标Path
|
||||||
|
*/
|
||||||
|
private Path resolveTarget(Path file) {
|
||||||
|
return fileSystem.getPath(source.relativize(file).toString());
|
||||||
|
}
|
||||||
|
}
|
@@ -656,6 +656,20 @@ public class PathUtil {
|
|||||||
return mkdir(path.getParent());
|
return mkdir(path.getParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取{@link Path}文件名
|
||||||
|
*
|
||||||
|
* @param path {@link Path}
|
||||||
|
* @return 文件名
|
||||||
|
* @since 5.7.15
|
||||||
|
*/
|
||||||
|
public static String getName(Path path) {
|
||||||
|
if (null == path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return path.getFileName().toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除文件或空目录,不追踪软链
|
* 删除文件或空目录,不追踪软链
|
||||||
*
|
*
|
||||||
|
@@ -1,11 +1,7 @@
|
|||||||
package cn.hutool.core.io.file.visitor;
|
package cn.hutool.core.io.file.visitor;
|
||||||
|
|
||||||
import cn.hutool.core.io.file.PathUtil;
|
import cn.hutool.core.io.file.PathUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.sun.nio.zipfs.ZipFileSystem;
|
|
||||||
import com.sun.nio.zipfs.ZipPath;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.CopyOption;
|
import java.nio.file.CopyOption;
|
||||||
import java.nio.file.FileAlreadyExistsException;
|
import java.nio.file.FileAlreadyExistsException;
|
||||||
@@ -24,53 +20,48 @@ import java.nio.file.attribute.BasicFileAttributes;
|
|||||||
*/
|
*/
|
||||||
public class CopyVisitor extends SimpleFileVisitor<Path> {
|
public class CopyVisitor extends SimpleFileVisitor<Path> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 源Path,或基准路径,用于计算被拷贝文件的相对路径
|
||||||
|
*/
|
||||||
private final Path source;
|
private final Path source;
|
||||||
private final Path target;
|
private final Path target;
|
||||||
private boolean isTargetCreated;
|
|
||||||
private final boolean isZipFile;
|
|
||||||
private String dirRoot = null;
|
|
||||||
private final CopyOption[] copyOptions;
|
private final CopyOption[] copyOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记目标目录是否创建,省略每次判断目标是否存在
|
||||||
|
*/
|
||||||
|
private boolean isTargetCreated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param source 源Path
|
* @param source 源Path,或基准路径,用于计算被拷贝文件的相对路径
|
||||||
* @param target 目标Path
|
* @param target 目标Path
|
||||||
* @param copyOptions 拷贝选项,如跳过已存在等
|
* @param copyOptions 拷贝选项,如跳过已存在等
|
||||||
*/
|
*/
|
||||||
public CopyVisitor(Path source, Path target, CopyOption... copyOptions) {
|
public CopyVisitor(Path source, Path target, CopyOption... copyOptions) {
|
||||||
if(PathUtil.exists(target, false) && false == PathUtil.isDirectory(target)){
|
if (PathUtil.exists(target, false) && false == PathUtil.isDirectory(target)) {
|
||||||
throw new IllegalArgumentException("Target must be a directory");
|
throw new IllegalArgumentException("Target must be a directory");
|
||||||
}
|
}
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.isZipFile = target instanceof ZipPath;
|
|
||||||
this.copyOptions = copyOptions;
|
this.copyOptions = copyOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||||
throws IOException {
|
initTargetDir();
|
||||||
final Path targetDir;
|
// 将当前目录相对于源路径转换为相对于目标路径
|
||||||
if (isZipFile) {
|
final Path targetDir = resolveTarget(dir);
|
||||||
ZipPath zipPath = (ZipPath) target;
|
|
||||||
ZipFileSystem fileSystem = zipPath.getFileSystem();
|
// 在目录不存在的情况下,copy方法会创建新目录
|
||||||
if (dirRoot == null) {
|
|
||||||
targetDir = fileSystem.getPath(dir.getFileName().toString());
|
|
||||||
dirRoot = dir.getFileName().toString() + File.separator;
|
|
||||||
} else {
|
|
||||||
targetDir = fileSystem.getPath(dirRoot, StrUtil.subAfter(dir.toString(), dirRoot, false));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
initTarget();
|
|
||||||
// 将当前目录相对于源路径转换为相对于目标路径
|
|
||||||
targetDir = target.resolve(source.relativize(dir));
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
Files.copy(dir, targetDir, copyOptions);
|
Files.copy(dir, targetDir, copyOptions);
|
||||||
} catch (FileAlreadyExistsException e) {
|
} catch (FileAlreadyExistsException e) {
|
||||||
if (false == Files.isDirectory(targetDir))
|
if (false == Files.isDirectory(targetDir)) {
|
||||||
|
// 目标文件存在抛出异常,目录忽略
|
||||||
throw e;
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
@@ -78,25 +69,33 @@ public class CopyVisitor extends SimpleFileVisitor<Path> {
|
|||||||
@Override
|
@Override
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (isZipFile) {
|
initTargetDir();
|
||||||
if (dirRoot == null) {
|
// 如果目标存在,无论目录还是文件都抛出FileAlreadyExistsException异常,此处不做特别处理
|
||||||
Files.copy(file, target, copyOptions);
|
Files.copy(file, resolveTarget(file), copyOptions);
|
||||||
} else {
|
|
||||||
ZipPath zipPath = (ZipPath) target;
|
|
||||||
Files.copy(file, zipPath.getFileSystem().getPath(dirRoot, StrUtil.subAfter(file.toString(), dirRoot, false)), copyOptions);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
initTarget();
|
|
||||||
Files.copy(file, target.resolve(source.relativize(file)), copyOptions);
|
|
||||||
}
|
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据源文件或目录路径,拼接生成目标的文件或目录路径<br>
|
||||||
|
* 原理是首先截取源路径,得到相对路径,再和目标路径拼接
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 如:源路径是 /opt/test/,需要拷贝的文件是 /opt/test/a/a.txt,得到相对路径 a/a.txt<br>
|
||||||
|
* 目标路径是/home/,则得到最终目标路径是 /home/a/a.txt
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param file 需要拷贝的文件或目录Path
|
||||||
|
* @return 目标Path
|
||||||
|
*/
|
||||||
|
private Path resolveTarget(Path file) {
|
||||||
|
return target.resolve(source.relativize(file));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化目标文件或目录
|
* 初始化目标文件或目录
|
||||||
*/
|
*/
|
||||||
private void initTarget(){
|
private void initTargetDir() {
|
||||||
if(false == this.isTargetCreated){
|
if (false == this.isTargetCreated) {
|
||||||
PathUtil.mkdir(this.target);
|
PathUtil.mkdir(this.target);
|
||||||
this.isTargetCreated = true;
|
this.isTargetCreated = true;
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package cn.hutool.core.util;
|
|||||||
|
|
||||||
import cn.hutool.core.compress.Deflate;
|
import cn.hutool.core.compress.Deflate;
|
||||||
import cn.hutool.core.compress.Gzip;
|
import cn.hutool.core.compress.Gzip;
|
||||||
|
import cn.hutool.core.compress.ZipCopyVisitor;
|
||||||
import cn.hutool.core.compress.ZipReader;
|
import cn.hutool.core.compress.ZipReader;
|
||||||
import cn.hutool.core.compress.ZipWriter;
|
import cn.hutool.core.compress.ZipWriter;
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
@@ -10,7 +11,7 @@ import cn.hutool.core.io.FileUtil;
|
|||||||
import cn.hutool.core.io.IORuntimeException;
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.io.file.FileSystemUtil;
|
import cn.hutool.core.io.file.FileSystemUtil;
|
||||||
import cn.hutool.core.io.file.visitor.CopyVisitor;
|
import cn.hutool.core.io.file.PathUtil;
|
||||||
import cn.hutool.core.io.resource.Resource;
|
import cn.hutool.core.io.resource.Resource;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
@@ -22,12 +23,11 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.file.CopyOption;
|
||||||
import java.nio.file.FileAlreadyExistsException;
|
import java.nio.file.FileAlreadyExistsException;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -40,8 +40,8 @@ import java.util.zip.ZipOutputStream;
|
|||||||
/**
|
/**
|
||||||
* 压缩工具类
|
* 压缩工具类
|
||||||
*
|
*
|
||||||
* @see cn.hutool.core.compress.ZipWriter
|
|
||||||
* @author Looly
|
* @author Looly
|
||||||
|
* @see cn.hutool.core.compress.ZipWriter
|
||||||
*/
|
*/
|
||||||
public class ZipUtil {
|
public class ZipUtil {
|
||||||
|
|
||||||
@@ -84,25 +84,29 @@ public class ZipUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在zip文件中添加新文件, 如果已经存在则不会有效果
|
* 在zip文件中添加新文件或目录<br>
|
||||||
|
* 新文件添加在zip根目录,文件夹包括其本身和内容<br>
|
||||||
|
* 如果待添加文件夹是系统根路径(如/或c:/),则只复制文件夹下的内容
|
||||||
*
|
*
|
||||||
* @param zipFilePathStr zip文件存储路径
|
* @param zipPath zip文件的Path
|
||||||
* @param appendFilePathStr 待添加文件路径(可以是文件夹)
|
* @param appendFilePath 待添加文件Path(可以是文件夹)
|
||||||
|
* @param options 拷贝选项,可选是否覆盖等
|
||||||
|
* @since 5.7.15
|
||||||
*/
|
*/
|
||||||
public static void addFile(String zipFilePathStr, String appendFilePathStr) throws IOException {
|
public static void append(Path zipPath, Path appendFilePath, CopyOption... options) throws IOException {
|
||||||
Path zipPath = Paths.get(zipFilePathStr);
|
|
||||||
Path appendFilePath = Paths.get(appendFilePathStr);
|
|
||||||
|
|
||||||
try (FileSystem zipFileSystem = FileSystemUtil.createZip(zipPath.toString())) {
|
try (FileSystem zipFileSystem = FileSystemUtil.createZip(zipPath.toString())) {
|
||||||
Path root = zipFileSystem.getPath("/");
|
if (Files.isDirectory(appendFilePath)) {
|
||||||
Path dest = zipFileSystem.getPath(root.toString(), appendFilePath.getFileName().toString());
|
Path source = appendFilePath.getParent();
|
||||||
if (!Files.isDirectory(appendFilePath)) {
|
if (null == source) {
|
||||||
Files.copy(appendFilePath, dest, StandardCopyOption.COPY_ATTRIBUTES);
|
// 如果用户提供的是根路径,则不复制目录,直接复制目录下的内容
|
||||||
|
source = appendFilePath;
|
||||||
|
}
|
||||||
|
Files.walkFileTree(appendFilePath, new ZipCopyVisitor(source, zipFileSystem, options));
|
||||||
} else {
|
} else {
|
||||||
Files.walkFileTree(appendFilePath, new CopyVisitor(appendFilePath, zipFileSystem.getPath(zipFilePathStr)));
|
Files.copy(appendFilePath, zipFileSystem.getPath(PathUtil.getName(appendFilePath)), options);
|
||||||
}
|
}
|
||||||
} catch (FileAlreadyExistsException ignored) {
|
} catch (FileAlreadyExistsException ignored) {
|
||||||
// 文件已存在, 跳过
|
// 不覆盖情况下,文件已存在, 跳过
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +275,7 @@ public class ZipUtil {
|
|||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static void zip(ZipOutputStream zipOutputStream, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException {
|
public static void zip(ZipOutputStream zipOutputStream, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException {
|
||||||
try(final ZipWriter zipWriter = new ZipWriter(zipOutputStream)){
|
try (final ZipWriter zipWriter = new ZipWriter(zipOutputStream)) {
|
||||||
zipWriter.add(withSrcDir, filter, srcFiles);
|
zipWriter.add(withSrcDir, filter, srcFiles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,7 +374,7 @@ public class ZipUtil {
|
|||||||
throw new IllegalArgumentException("Paths length is not equals to ins length !");
|
throw new IllegalArgumentException("Paths length is not equals to ins length !");
|
||||||
}
|
}
|
||||||
|
|
||||||
try(final ZipWriter zipWriter = ZipWriter.of(zipFile, charset)){
|
try (final ZipWriter zipWriter = ZipWriter.of(zipFile, charset)) {
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
zipWriter.add(paths[i], ins[i]);
|
zipWriter.add(paths[i], ins[i]);
|
||||||
}
|
}
|
||||||
@@ -395,7 +399,7 @@ public class ZipUtil {
|
|||||||
throw new IllegalArgumentException("Paths length is not equals to ins length !");
|
throw new IllegalArgumentException("Paths length is not equals to ins length !");
|
||||||
}
|
}
|
||||||
|
|
||||||
try(final ZipWriter zipWriter = ZipWriter.of(out, DEFAULT_CHARSET)){
|
try (final ZipWriter zipWriter = ZipWriter.of(out, DEFAULT_CHARSET)) {
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
zipWriter.add(paths[i], ins[i]);
|
zipWriter.add(paths[i], ins[i]);
|
||||||
}
|
}
|
||||||
@@ -419,7 +423,7 @@ public class ZipUtil {
|
|||||||
throw new IllegalArgumentException("Paths length is not equals to ins length !");
|
throw new IllegalArgumentException("Paths length is not equals to ins length !");
|
||||||
}
|
}
|
||||||
|
|
||||||
try(final ZipWriter zipWriter = new ZipWriter(zipOutputStream)){
|
try (final ZipWriter zipWriter = new ZipWriter(zipOutputStream)) {
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
zipWriter.add(paths[i], ins[i]);
|
zipWriter.add(paths[i], ins[i]);
|
||||||
}
|
}
|
||||||
@@ -559,7 +563,7 @@ public class ZipUtil {
|
|||||||
StrUtil.format("Target path [{}] exist!", outFile.getAbsolutePath()));
|
StrUtil.format("Target path [{}] exist!", outFile.getAbsolutePath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
try(final ZipReader reader = new ZipReader(zipFile)){
|
try (final ZipReader reader = new ZipReader(zipFile)) {
|
||||||
reader.readTo(outFile);
|
reader.readTo(outFile);
|
||||||
}
|
}
|
||||||
return outFile;
|
return outFile;
|
||||||
@@ -602,7 +606,7 @@ public class ZipUtil {
|
|||||||
* @since 5.5.2
|
* @since 5.5.2
|
||||||
*/
|
*/
|
||||||
public static void read(ZipFile zipFile, Consumer<ZipEntry> consumer) {
|
public static void read(ZipFile zipFile, Consumer<ZipEntry> consumer) {
|
||||||
try(final ZipReader reader = new ZipReader(zipFile)){
|
try (final ZipReader reader = new ZipReader(zipFile)) {
|
||||||
reader.read(consumer);
|
reader.read(consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -636,7 +640,7 @@ public class ZipUtil {
|
|||||||
* @since 4.5.8
|
* @since 4.5.8
|
||||||
*/
|
*/
|
||||||
public static File unzip(ZipInputStream zipStream, File outFile) throws UtilException {
|
public static File unzip(ZipInputStream zipStream, File outFile) throws UtilException {
|
||||||
try(final ZipReader reader = new ZipReader(zipStream)){
|
try (final ZipReader reader = new ZipReader(zipStream)) {
|
||||||
reader.readTo(outFile);
|
reader.readTo(outFile);
|
||||||
}
|
}
|
||||||
return outFile;
|
return outFile;
|
||||||
@@ -650,7 +654,7 @@ public class ZipUtil {
|
|||||||
* @since 5.5.2
|
* @since 5.5.2
|
||||||
*/
|
*/
|
||||||
public static void read(ZipInputStream zipStream, Consumer<ZipEntry> consumer) {
|
public static void read(ZipInputStream zipStream, Consumer<ZipEntry> consumer) {
|
||||||
try(final ZipReader reader = new ZipReader(zipStream)){
|
try (final ZipReader reader = new ZipReader(zipStream)) {
|
||||||
reader.read(consumer);
|
reader.read(consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -702,7 +706,7 @@ public class ZipUtil {
|
|||||||
* @since 4.1.8
|
* @since 4.1.8
|
||||||
*/
|
*/
|
||||||
public static byte[] unzipFileBytes(File zipFile, Charset charset, String name) {
|
public static byte[] unzipFileBytes(File zipFile, Charset charset, String name) {
|
||||||
try(final ZipReader reader = ZipReader.of(zipFile, charset)){
|
try (final ZipReader reader = ZipReader.of(zipFile, charset)) {
|
||||||
return IoUtil.readBytes(reader.get(name));
|
return IoUtil.readBytes(reader.get(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,7 @@ import java.util.List;
|
|||||||
public class ZipUtilTest {
|
public class ZipUtilTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addFileTest() throws IOException {
|
public void appendTest() throws IOException {
|
||||||
File appendFile = FileUtil.file("test-zip/addFile.txt");
|
File appendFile = FileUtil.file("test-zip/addFile.txt");
|
||||||
File zipFile = FileUtil.file("test-zip/test.zip");
|
File zipFile = FileUtil.file("test-zip/test.zip");
|
||||||
|
|
||||||
@@ -34,23 +34,27 @@ public class ZipUtilTest {
|
|||||||
FileUtil.copy(zipFile, tempZipFile, true);
|
FileUtil.copy(zipFile, tempZipFile, true);
|
||||||
|
|
||||||
// test file add
|
// test file add
|
||||||
List<String> beforeNames = zipEntryNames(zipFile);
|
List<String> beforeNames = zipEntryNames(tempZipFile);
|
||||||
ZipUtil.addFile(zipFile.getAbsolutePath(), appendFile.getAbsolutePath());
|
ZipUtil.append(tempZipFile.toPath(), appendFile.toPath());
|
||||||
List<String> afterNames = zipEntryNames(zipFile);
|
List<String> afterNames = zipEntryNames(tempZipFile);
|
||||||
|
|
||||||
|
// 确认增加了文件
|
||||||
|
Assert.assertEquals(beforeNames.size() + 1, afterNames.size());
|
||||||
Assert.assertTrue(afterNames.containsAll(beforeNames));
|
Assert.assertTrue(afterNames.containsAll(beforeNames));
|
||||||
Assert.assertTrue(afterNames.contains(appendFile.getName()));
|
Assert.assertTrue(afterNames.contains(appendFile.getName()));
|
||||||
|
|
||||||
// test dir add
|
// test dir add
|
||||||
beforeNames = afterNames;
|
beforeNames = zipEntryNames(tempZipFile);
|
||||||
File addDirFile = FileUtil.file("test-zip/test-add");
|
File addDirFile = FileUtil.file("test-zip/test-add");
|
||||||
ZipUtil.addFile(zipFile.getAbsolutePath(), addDirFile.getAbsolutePath());
|
ZipUtil.append(tempZipFile.toPath(), addDirFile.toPath());
|
||||||
afterNames = zipEntryNames(zipFile);
|
afterNames = zipEntryNames(tempZipFile);
|
||||||
|
|
||||||
|
// 确认增加了文件和目录,增加目录和目录下一个文件,故此处+2
|
||||||
|
Assert.assertEquals(beforeNames.size() + 2, afterNames.size());
|
||||||
Assert.assertTrue(afterNames.containsAll(beforeNames));
|
Assert.assertTrue(afterNames.containsAll(beforeNames));
|
||||||
Assert.assertTrue(afterNames.contains(appendFile.getName()));
|
Assert.assertTrue(afterNames.contains(appendFile.getName()));
|
||||||
|
|
||||||
// rollback
|
// rollback
|
||||||
FileUtil.copy(tempZipFile, zipFile, true);
|
|
||||||
Assert.assertTrue(String.format("delete temp file %s failed", tempZipFile.getCanonicalPath()), tempZipFile.delete());
|
Assert.assertTrue(String.format("delete temp file %s failed", tempZipFile.getCanonicalPath()), tempZipFile.delete());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
1
|
Reference in New Issue
Block a user