mirror of
https://gitee.com/dromara/hutool.git
synced 2025-05-16 21:19:35 +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;
|
package cn.hutool.extra.compress.extractor;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Filter;
|
import cn.hutool.core.lang.Filter;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 归档数据解包封装,用于将zip、tar等包解包为文件
|
* 归档数据解包封装,用于将zip、tar等包解包为文件
|
||||||
@ -29,7 +32,48 @@ public interface Extractor extends Closeable {
|
|||||||
* @param targetDir 目标目录
|
* @param targetDir 目标目录
|
||||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,{@code null}表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
* @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时释放。
|
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void extract(File targetDir, Filter<ArchiveEntry> filter) {
|
public void extract(File targetDir, int stripComponents, Filter<ArchiveEntry> filter) {
|
||||||
try {
|
try {
|
||||||
extractInternal(targetDir, filter);
|
extractInternal(targetDir, stripComponents, filter);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IORuntimeException(e);
|
throw new IORuntimeException(e);
|
||||||
} finally {
|
} finally {
|
||||||
@ -151,10 +151,11 @@ public class SevenZExtractor implements Extractor, RandomAccess {
|
|||||||
* 释放(解压)到指定目录
|
* 释放(解压)到指定目录
|
||||||
*
|
*
|
||||||
* @param targetDir 目标目录
|
* @param targetDir 目标目录
|
||||||
|
* @param stripComponents 清除(剥离)压缩包里面的 n 级文件夹名
|
||||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||||
* @throws IOException IO异常
|
* @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.");
|
Assert.isTrue(null != targetDir && ((false == targetDir.exists()) || targetDir.isDirectory()), "target must be dir.");
|
||||||
final SevenZFile sevenZFile = this.sevenZFile;
|
final SevenZFile sevenZFile = this.sevenZFile;
|
||||||
SevenZArchiveEntry entry;
|
SevenZArchiveEntry entry;
|
||||||
@ -163,7 +164,12 @@ public class SevenZExtractor implements Extractor, RandomAccess {
|
|||||||
if (null != filter && false == filter.accept(entry)) {
|
if (null != filter && false == filter.accept(entry)) {
|
||||||
continue;
|
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()) {
|
if (entry.isDirectory()) {
|
||||||
// 创建对应目录
|
// 创建对应目录
|
||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
@ -104,9 +104,9 @@ public class StreamExtractor implements Extractor{
|
|||||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void extract(File targetDir, Filter<ArchiveEntry> filter) {
|
public void extract(File targetDir, int stripComponents, Filter<ArchiveEntry> filter) {
|
||||||
try {
|
try {
|
||||||
extractInternal(targetDir, filter);
|
extractInternal(targetDir, stripComponents, filter);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IORuntimeException(e);
|
throw new IORuntimeException(e);
|
||||||
} finally {
|
} finally {
|
||||||
@ -118,10 +118,11 @@ public class StreamExtractor implements Extractor{
|
|||||||
* 释放(解压)到指定目录
|
* 释放(解压)到指定目录
|
||||||
*
|
*
|
||||||
* @param targetDir 目标目录
|
* @param targetDir 目标目录
|
||||||
|
* @param stripComponents 清除(剥离)压缩包里面的 n 级文件夹名
|
||||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||||
* @throws IOException IO异常
|
* @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.");
|
Assert.isTrue(null != targetDir && ((false == targetDir.exists()) || targetDir.isDirectory()), "target must be dir.");
|
||||||
final ArchiveInputStream in = this.in;
|
final ArchiveInputStream in = this.in;
|
||||||
ArchiveEntry entry;
|
ArchiveEntry entry;
|
||||||
@ -134,7 +135,12 @@ public class StreamExtractor implements Extractor{
|
|||||||
// 无法读取的文件直接跳过
|
// 无法读取的文件直接跳过
|
||||||
continue;
|
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()) {
|
if (entry.isDirectory()) {
|
||||||
// 创建对应目录
|
// 创建对应目录
|
||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
@ -6,6 +6,8 @@ import cn.hutool.extra.compress.extractor.Extractor;
|
|||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
public class ExtractorTest {
|
public class ExtractorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -38,4 +40,30 @@ public class ExtractorTest {
|
|||||||
|
|
||||||
extractor.extract(FileUtil.file("d:/test/tgz/"));
|
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