mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
Merge pull request !441 from 申劭明/v5-dev-20211015
This commit is contained in:
commit
8a8dbd1816
@ -1,7 +1,11 @@
|
|||||||
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;
|
||||||
@ -23,6 +27,8 @@ public class CopyVisitor extends SimpleFileVisitor<Path> {
|
|||||||
private final Path source;
|
private final Path source;
|
||||||
private final Path target;
|
private final Path target;
|
||||||
private boolean isTargetCreated;
|
private boolean isTargetCreated;
|
||||||
|
private final boolean isZipFile;
|
||||||
|
private String dirRoot = null;
|
||||||
private final CopyOption[] copyOptions;
|
private final CopyOption[] copyOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,15 +44,28 @@ public class CopyVisitor extends SimpleFileVisitor<Path> {
|
|||||||
}
|
}
|
||||||
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 {
|
||||||
initTarget();
|
final Path targetDir;
|
||||||
// 将当前目录相对于源路径转换为相对于目标路径
|
if (isZipFile) {
|
||||||
final Path targetDir = target.resolve(source.relativize(dir));
|
ZipPath zipPath = (ZipPath) target;
|
||||||
|
ZipFileSystem fileSystem = zipPath.getFileSystem();
|
||||||
|
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) {
|
||||||
@ -59,8 +78,17 @@ 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 {
|
||||||
initTarget();
|
if (isZipFile) {
|
||||||
Files.copy(file, target.resolve(source.relativize(file)), copyOptions);
|
if (dirRoot == null) {
|
||||||
|
Files.copy(file, target, 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ import cn.hutool.core.io.FastByteArrayOutputStream;
|
|||||||
import cn.hutool.core.io.FileUtil;
|
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.visitor.CopyVisitor;
|
||||||
import cn.hutool.core.io.resource.Resource;
|
import cn.hutool.core.io.resource.Resource;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
@ -20,6 +22,12 @@ 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.FileAlreadyExistsException;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
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;
|
||||||
@ -75,6 +83,29 @@ public class ZipUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在zip文件中添加新文件, 如果已经存在则不会有效果
|
||||||
|
*
|
||||||
|
* @param zipFilePathStr zip文件存储路径
|
||||||
|
* @param appendFilePathStr 待添加文件路径(可以是文件夹)
|
||||||
|
*/
|
||||||
|
public static void addFile(String zipFilePathStr, String appendFilePathStr) throws IOException {
|
||||||
|
Path zipPath = Paths.get(zipFilePathStr);
|
||||||
|
Path appendFilePath = Paths.get(appendFilePathStr);
|
||||||
|
|
||||||
|
try (FileSystem zipFileSystem = FileSystemUtil.createZip(zipPath.toString())) {
|
||||||
|
Path root = zipFileSystem.getPath("/");
|
||||||
|
Path dest = zipFileSystem.getPath(root.toString(), appendFilePath.getFileName().toString());
|
||||||
|
if (!Files.isDirectory(appendFilePath)) {
|
||||||
|
Files.copy(appendFilePath, dest, StandardCopyOption.COPY_ATTRIBUTES);
|
||||||
|
} else {
|
||||||
|
Files.walkFileTree(appendFilePath, new CopyVisitor(appendFilePath, zipFileSystem.getPath(zipFilePathStr)));
|
||||||
|
}
|
||||||
|
} catch (FileAlreadyExistsException ignored) {
|
||||||
|
// 文件已存在, 跳过
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打包到当前目录,使用默认编码UTF-8
|
* 打包到当前目录,使用默认编码UTF-8
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.core.util;
|
package cn.hutool.core.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.compress.ZipReader;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.io.IORuntimeException;
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
import cn.hutool.core.lang.Console;
|
import cn.hutool.core.lang.Console;
|
||||||
@ -12,6 +13,8 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ZipUtil}单元测试
|
* {@link ZipUtil}单元测试
|
||||||
@ -20,6 +23,50 @@ import java.nio.charset.Charset;
|
|||||||
*/
|
*/
|
||||||
public class ZipUtilTest {
|
public class ZipUtilTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addFileTest() throws IOException {
|
||||||
|
File appendFile = FileUtil.file("test-zip/addFile.txt");
|
||||||
|
File zipFile = FileUtil.file("test-zip/test.zip");
|
||||||
|
|
||||||
|
// 用于测试完成后将被测试文件恢复
|
||||||
|
File tempZipFile = FileUtil.createTempFile(FileUtil.file("test-zip"));
|
||||||
|
tempZipFile.deleteOnExit();
|
||||||
|
FileUtil.copy(zipFile, tempZipFile, true);
|
||||||
|
|
||||||
|
// test file add
|
||||||
|
List<String> beforeNames = zipEntryNames(zipFile);
|
||||||
|
ZipUtil.addFile(zipFile.getAbsolutePath(), appendFile.getAbsolutePath());
|
||||||
|
List<String> afterNames = zipEntryNames(zipFile);
|
||||||
|
Assert.assertTrue(afterNames.containsAll(beforeNames));
|
||||||
|
Assert.assertTrue(afterNames.contains(appendFile.getName()));
|
||||||
|
|
||||||
|
// test dir add
|
||||||
|
beforeNames = afterNames;
|
||||||
|
File addDirFile = FileUtil.file("test-zip/test-add");
|
||||||
|
ZipUtil.addFile(zipFile.getAbsolutePath(), addDirFile.getAbsolutePath());
|
||||||
|
afterNames = zipEntryNames(zipFile);
|
||||||
|
|
||||||
|
Assert.assertTrue(afterNames.containsAll(beforeNames));
|
||||||
|
Assert.assertTrue(afterNames.contains(appendFile.getName()));
|
||||||
|
|
||||||
|
// rollback
|
||||||
|
FileUtil.copy(tempZipFile, zipFile, true);
|
||||||
|
Assert.assertTrue(String.format("delete temp file %s failed", tempZipFile.getCanonicalPath()), tempZipFile.delete());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取zip文件中所有一级文件/文件夹的name
|
||||||
|
*
|
||||||
|
* @param zipFile 待测试的zip文件
|
||||||
|
* @return zip文件中一级目录下的所有文件/文件夹名
|
||||||
|
*/
|
||||||
|
private List<String> zipEntryNames(File zipFile) {
|
||||||
|
List<String> fileNames = new ArrayList<>();
|
||||||
|
ZipReader reader = ZipReader.of(zipFile, CharsetUtil.CHARSET_UTF_8);
|
||||||
|
reader.read(zipEntry -> fileNames.add(zipEntry.getName()));
|
||||||
|
reader.close();
|
||||||
|
return fileNames;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
|
2
hutool-core/src/test/resources/test-zip/addFile.txt
Normal file
2
hutool-core/src/test/resources/test-zip/addFile.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
this file will be used to add into the test.zip
|
||||||
|
before the add action, the test.zip won't have this file.
|
BIN
hutool-core/src/test/resources/test-zip/test.zip
Normal file
BIN
hutool-core/src/test/resources/test-zip/test.zip
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user