mirror of
https://gitee.com/dromara/hutool.git
synced 2025-05-17 05:29:34 +08:00
feat CompressUtil 新增 stripComponents 参数 #I67MIK
This commit is contained in:
parent
ecde508346
commit
b92d98e286
@ -1,10 +1,13 @@
|
||||
package cn.hutool.extra.compress.extractor;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 归档数据解包封装,用于将zip、tar等包解包为文件
|
||||
@ -29,7 +32,48 @@ public interface Extractor extends Closeable {
|
||||
* @param targetDir 目标目录
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,{@code null}表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
*/
|
||||
void extract(File targetDir, Filter<ArchiveEntry> filter);
|
||||
default void extract(File targetDir, Filter<ArchiveEntry> filter) {
|
||||
this.extract(targetDir, 0, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放(解压)到指定目录,结束后自动关闭流,此方法只能调用一次
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
* @param stripComponents 清除(剥离)压缩包里面的 n 级文件夹名
|
||||
*/
|
||||
default void extract(File targetDir, int stripComponents) {
|
||||
this.extract(targetDir, stripComponents, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放(解压)到指定目录,结束后自动关闭流,此方法只能调用一次
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
* @param stripComponents 清除(剥离)压缩包里面的 n 级文件夹名
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,{@code null}表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
*/
|
||||
void extract(File targetDir, int stripComponents, Filter<ArchiveEntry> filter);
|
||||
|
||||
/**
|
||||
* 剥离名称
|
||||
*
|
||||
* @param name 文件名
|
||||
* @param stripComponents 剥离层级
|
||||
* @return 剥离后的文件名
|
||||
*/
|
||||
default String stripName(String name, int stripComponents) {
|
||||
if (stripComponents <= 0) {
|
||||
return name;
|
||||
}
|
||||
List<String> nameList = StrUtil.splitTrim(name, StrUtil.SLASH);
|
||||
int size = nameList.size();
|
||||
if (size > stripComponents) {
|
||||
nameList = CollUtil.sub(nameList, stripComponents, size);
|
||||
return CollUtil.join(nameList, StrUtil.SLASH);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无异常关闭
|
||||
|
@ -99,9 +99,9 @@ public class SevenZExtractor implements Extractor, RandomAccess {
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
*/
|
||||
@Override
|
||||
public void extract(File targetDir, Filter<ArchiveEntry> filter) {
|
||||
public void extract(File targetDir, int stripComponents, Filter<ArchiveEntry> filter) {
|
||||
try {
|
||||
extractInternal(targetDir, filter);
|
||||
extractInternal(targetDir, stripComponents, filter);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
@ -151,10 +151,11 @@ public class SevenZExtractor implements Extractor, RandomAccess {
|
||||
* 释放(解压)到指定目录
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
* @param stripComponents 清除(剥离)压缩包里面的 n 级文件夹名
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
private void extractInternal(File targetDir, Filter<ArchiveEntry> filter) throws IOException {
|
||||
private void extractInternal(File targetDir, int stripComponents, Filter<ArchiveEntry> filter) throws IOException {
|
||||
Assert.isTrue(null != targetDir && ((false == targetDir.exists()) || targetDir.isDirectory()), "target must be dir.");
|
||||
final SevenZFile sevenZFile = this.sevenZFile;
|
||||
SevenZArchiveEntry entry;
|
||||
@ -163,7 +164,12 @@ public class SevenZExtractor implements Extractor, RandomAccess {
|
||||
if (null != filter && false == filter.accept(entry)) {
|
||||
continue;
|
||||
}
|
||||
outItemFile = FileUtil.file(targetDir, entry.getName());
|
||||
String entryName = this.stripName(entry.getName(), stripComponents);
|
||||
if (entryName == null) {
|
||||
// 剥离文件夹层级
|
||||
continue;
|
||||
}
|
||||
outItemFile = FileUtil.file(targetDir, entryName);
|
||||
if (entry.isDirectory()) {
|
||||
// 创建对应目录
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
|
@ -104,9 +104,9 @@ public class StreamExtractor implements Extractor{
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
*/
|
||||
@Override
|
||||
public void extract(File targetDir, Filter<ArchiveEntry> filter) {
|
||||
public void extract(File targetDir, int stripComponents, Filter<ArchiveEntry> filter) {
|
||||
try {
|
||||
extractInternal(targetDir, filter);
|
||||
extractInternal(targetDir, stripComponents, filter);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
@ -118,10 +118,11 @@ public class StreamExtractor implements Extractor{
|
||||
* 释放(解压)到指定目录
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
* @param stripComponents 清除(剥离)压缩包里面的 n 级文件夹名
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
private void extractInternal(File targetDir, Filter<ArchiveEntry> filter) throws IOException {
|
||||
private void extractInternal(File targetDir, int stripComponents, Filter<ArchiveEntry> filter) throws IOException {
|
||||
Assert.isTrue(null != targetDir && ((false == targetDir.exists()) || targetDir.isDirectory()), "target must be dir.");
|
||||
final ArchiveInputStream in = this.in;
|
||||
ArchiveEntry entry;
|
||||
@ -134,7 +135,12 @@ public class StreamExtractor implements Extractor{
|
||||
// 无法读取的文件直接跳过
|
||||
continue;
|
||||
}
|
||||
outItemFile = FileUtil.file(targetDir, entry.getName());
|
||||
String entryName = this.stripName(entry.getName(), stripComponents);
|
||||
if (entryName == null) {
|
||||
// 剥离文件夹层级
|
||||
continue;
|
||||
}
|
||||
outItemFile = FileUtil.file(targetDir, entryName);
|
||||
if (entry.isDirectory()) {
|
||||
// 创建对应目录
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
|
@ -6,6 +6,8 @@ import cn.hutool.extra.compress.extractor.Extractor;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ExtractorTest {
|
||||
|
||||
@Test
|
||||
@ -38,4 +40,30 @@ public class ExtractorTest {
|
||||
|
||||
extractor.extract(FileUtil.file("d:/test/tgz/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void sevenZTest2() {
|
||||
File targetDir = FileUtil.file("d:/test/sevenZ2/");
|
||||
FileUtil.clean(targetDir);
|
||||
//
|
||||
Extractor extractor = CompressUtil.createExtractor(
|
||||
CharsetUtil.defaultCharset(),
|
||||
FileUtil.file("D:/System-Data/Downloads/apache-tomcat-10.0.27.7z"));
|
||||
|
||||
extractor.extract(targetDir, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void zipTest2() {
|
||||
File targetDir = FileUtil.file("d:/test/zip2/");
|
||||
FileUtil.clean(targetDir);
|
||||
//
|
||||
Extractor extractor = CompressUtil.createExtractor(
|
||||
CharsetUtil.defaultCharset(),
|
||||
FileUtil.file("D:/System-Data/Downloads/apache-tomcat-10.0.27.zip"));
|
||||
|
||||
extractor.extract(targetDir, 1);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user