mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add 7zip
This commit is contained in:
parent
71ab8335ce
commit
e025096896
@ -3,7 +3,7 @@
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.5.0 (2020-11-11)
|
||||
# 5.5.0 (2020-11-14)
|
||||
|
||||
### 新特性
|
||||
* 【core 】 NumberUtil.parseInt等支持123,2.00这类数字(issue#I23ORQ@Gitee)
|
||||
|
@ -3,9 +3,14 @@ package cn.hutool.extra.compress;
|
||||
import cn.hutool.extra.compress.archiver.Archiver;
|
||||
import cn.hutool.extra.compress.archiver.SevenZArchiver;
|
||||
import cn.hutool.extra.compress.archiver.StreamArchiver;
|
||||
import cn.hutool.extra.compress.extractor.Extractor;
|
||||
import cn.hutool.extra.compress.extractor.SenvenZExtractor;
|
||||
import cn.hutool.extra.compress.extractor.StreamExtractor;
|
||||
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
||||
import org.apache.commons.compress.archivers.StreamingNotSupportedException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
@ -13,8 +18,8 @@ import java.nio.charset.Charset;
|
||||
* 压缩工具类<br>
|
||||
* 基于commons-compress的压缩解压封装
|
||||
*
|
||||
* @since 5.5.0
|
||||
* @author looly
|
||||
* @since 5.5.0
|
||||
*/
|
||||
public class CompressUtil {
|
||||
|
||||
@ -54,7 +59,7 @@ public class CompressUtil {
|
||||
*
|
||||
* @param charset 编码
|
||||
* @param archiverName 归档类型名称,见{@link ArchiveStreamFactory}
|
||||
* @param out 归档输出的流
|
||||
* @param out 归档输出的流
|
||||
* @return Archiver
|
||||
*/
|
||||
public static Archiver createArchiver(Charset charset, String archiverName, OutputStream out) {
|
||||
@ -63,4 +68,104 @@ public class CompressUtil {
|
||||
}
|
||||
return StreamArchiver.create(charset, archiverName, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建归档解包器,支持:
|
||||
* <ul>
|
||||
* <li>{@link ArchiveStreamFactory#AR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#CPIO}</li>
|
||||
* <li>{@link ArchiveStreamFactory#JAR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#TAR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#ZIP}</li>
|
||||
* <li>{@link ArchiveStreamFactory#SEVEN_Z}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param charset 编码,7z格式此参数无效
|
||||
* @param file 归档文件
|
||||
* @return {@link Extractor}
|
||||
*/
|
||||
public static Extractor createExtractor(Charset charset, File file) {
|
||||
return createExtractor(charset, null, file);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建归档解包器,支持:
|
||||
* <ul>
|
||||
* <li>{@link ArchiveStreamFactory#AR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#CPIO}</li>
|
||||
* <li>{@link ArchiveStreamFactory#JAR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#TAR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#ZIP}</li>
|
||||
* <li>{@link ArchiveStreamFactory#SEVEN_Z}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param charset 编码,7z格式此参数无效
|
||||
* @param archiverName 归档类型名称,见{@link ArchiveStreamFactory},null表示自动识别
|
||||
* @param file 归档文件
|
||||
* @return {@link Extractor}
|
||||
*/
|
||||
public static Extractor createExtractor(Charset charset, String archiverName, File file) {
|
||||
if (ArchiveStreamFactory.SEVEN_Z.equalsIgnoreCase(archiverName)) {
|
||||
return new SenvenZExtractor(file);
|
||||
}
|
||||
try{
|
||||
return new StreamExtractor(charset, archiverName, file);
|
||||
} catch (CompressException e){
|
||||
final Throwable cause = e.getCause();
|
||||
if(cause instanceof StreamingNotSupportedException && cause.getMessage().contains("7z")){
|
||||
return new SenvenZExtractor(file);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建归档解包器,支持:
|
||||
* <ul>
|
||||
* <li>{@link ArchiveStreamFactory#AR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#CPIO}</li>
|
||||
* <li>{@link ArchiveStreamFactory#JAR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#TAR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#ZIP}</li>
|
||||
* <li>{@link ArchiveStreamFactory#SEVEN_Z}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param charset 编码,7z格式此参数无效
|
||||
* @param in 归档输入的流
|
||||
* @return {@link Extractor}
|
||||
*/
|
||||
public static Extractor createExtractor(Charset charset, InputStream in) {
|
||||
return createExtractor(charset, null, in);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建归档解包器,支持:
|
||||
* <ul>
|
||||
* <li>{@link ArchiveStreamFactory#AR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#CPIO}</li>
|
||||
* <li>{@link ArchiveStreamFactory#JAR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#TAR}</li>
|
||||
* <li>{@link ArchiveStreamFactory#ZIP}</li>
|
||||
* <li>{@link ArchiveStreamFactory#SEVEN_Z}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param charset 编码,7z格式此参数无效
|
||||
* @param archiverName 归档类型名称,见{@link ArchiveStreamFactory},null表示自动识别
|
||||
* @param in 归档输入的流
|
||||
* @return {@link Extractor}
|
||||
*/
|
||||
public static Extractor createExtractor(Charset charset, String archiverName, InputStream in) {
|
||||
if (ArchiveStreamFactory.SEVEN_Z.equalsIgnoreCase(archiverName)) {
|
||||
return new SenvenZExtractor(in);
|
||||
}
|
||||
try{
|
||||
return new StreamExtractor(charset, archiverName, in);
|
||||
} catch (CompressException e){
|
||||
final Throwable cause = e.getCause();
|
||||
if(cause instanceof StreamingNotSupportedException && cause.getMessage().contains("7z")){
|
||||
return new SenvenZExtractor(in);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package cn.hutool.extra.compress.archiver;
|
||||
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
/**
|
||||
* 数据归档封装,归档即将几个文件或目录打成一个压缩包
|
||||
@ -27,10 +27,10 @@ public interface Archiver extends Closeable {
|
||||
* 将文件或目录加入归档,目录采取递归读取方式按照层级加入
|
||||
*
|
||||
* @param file 文件或目录
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link FileFilter#accept(File)}为true时加入。
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link Filter#accept(Object)}为true时加入。
|
||||
* @return this
|
||||
*/
|
||||
default Archiver add(File file, FileFilter filter) {
|
||||
default Archiver add(File file, Filter<File> filter) {
|
||||
return add(file, StrUtil.SLASH, filter);
|
||||
}
|
||||
|
||||
@ -39,10 +39,10 @@ public interface Archiver extends Closeable {
|
||||
*
|
||||
* @param file 文件或目录
|
||||
* @param path 文件或目录的初始路径,null表示位于根路径
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link FileFilter#accept(File)}为true时加入。
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link Filter#accept(Object)}为true时加入。
|
||||
* @return this
|
||||
*/
|
||||
Archiver add(File file, String path, FileFilter filter);
|
||||
Archiver add(File file, String path, Filter<File> filter);
|
||||
|
||||
/**
|
||||
* 结束已经增加的文件归档,此方法不会关闭归档流,可以继续添加文件
|
||||
|
@ -3,12 +3,12 @@ package cn.hutool.extra.compress.archiver;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
|
||||
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
@ -67,7 +67,7 @@ public class SevenZArchiver implements Archiver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SevenZArchiver add(File file, String path, FileFilter filter) {
|
||||
public SevenZArchiver add(File file, String path, Filter<File> filter) {
|
||||
try {
|
||||
addInternal(file, path, filter);
|
||||
} catch (IOException e) {
|
||||
@ -108,9 +108,9 @@ public class SevenZArchiver implements Archiver {
|
||||
*
|
||||
* @param file 文件或目录
|
||||
* @param path 文件或目录的初始路径,null表示位于根路径
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link FileFilter#accept(File)}为true时加入。
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link Filter#accept(Object)}为true时加入。
|
||||
*/
|
||||
private void addInternal(File file, String path, FileFilter filter) throws IOException {
|
||||
private void addInternal(File file, String path, Filter<File> filter) throws IOException {
|
||||
if (null != filter && false == filter.accept(file)) {
|
||||
return;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package cn.hutool.extra.compress.archiver;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.compress.CompressException;
|
||||
import org.apache.commons.compress.archivers.ArchiveException;
|
||||
@ -12,7 +13,6 @@ import org.apache.commons.compress.archivers.ar.ArArchiveOutputStream;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
@ -97,12 +97,12 @@ public class StreamArchiver implements Archiver {
|
||||
*
|
||||
* @param file 文件或目录
|
||||
* @param path 文件或目录的初始路径,null表示位于根路径
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link FileFilter#accept(File)}为true时加入。
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link Filter#accept(Object)}为true时加入。
|
||||
* @return this
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
@Override
|
||||
public StreamArchiver add(File file, String path, FileFilter filter) throws IORuntimeException {
|
||||
public StreamArchiver add(File file, String path, Filter<File> filter) throws IORuntimeException {
|
||||
try {
|
||||
addInternal(file, path, filter);
|
||||
} catch (IOException e) {
|
||||
@ -141,9 +141,9 @@ public class StreamArchiver implements Archiver {
|
||||
*
|
||||
* @param file 文件或目录
|
||||
* @param path 文件或目录的初始路径,null表示位于根路径
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link FileFilter#accept(File)}为true时加入。
|
||||
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link Filter#accept(Object)}为true时加入。
|
||||
*/
|
||||
private void addInternal(File file, String path, FileFilter filter) throws IOException {
|
||||
private void addInternal(File file, String path, Filter<File> filter) throws IOException {
|
||||
if (null != filter && false == filter.accept(file)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,11 +1,39 @@
|
||||
package cn.hutool.extra.compress.extractor;
|
||||
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 数据解包封装,用于将zip、tar等包解包为文件
|
||||
* 归档数据解包封装,用于将zip、tar等包解包为文件
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.5.0
|
||||
*/
|
||||
public interface Extractor {
|
||||
public interface Extractor extends Closeable {
|
||||
|
||||
/**
|
||||
* 释放(解压)到指定目录,结束后自动关闭流,此方法只能调用一次
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
*/
|
||||
default void extract(File targetDir){
|
||||
extract(targetDir, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放(解压)到指定目录,结束后自动关闭流,此方法只能调用一次
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
*/
|
||||
void extract(File targetDir, Filter<ArchiveEntry> filter);
|
||||
|
||||
/**
|
||||
* 无异常关闭
|
||||
*/
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
|
@ -0,0 +1,142 @@
|
||||
package cn.hutool.extra.compress.extractor;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
|
||||
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
|
||||
/**
|
||||
* 7z格式数据解压器,即将归档打包的数据释放
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.5.0
|
||||
*/
|
||||
public class SenvenZExtractor implements Extractor {
|
||||
|
||||
private final SevenZFile sevenZFile;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param file 包文件
|
||||
*/
|
||||
public SenvenZExtractor(File file) {
|
||||
this(file, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param file 包文件
|
||||
* @param password 密码,null表示无密码
|
||||
*/
|
||||
public SenvenZExtractor(File file, char[] password) {
|
||||
try {
|
||||
this.sevenZFile = new SevenZFile(file, password);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param in 包流
|
||||
*/
|
||||
public SenvenZExtractor(InputStream in) {
|
||||
this(in, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param in 包流
|
||||
* @param password 密码,null表示无密码
|
||||
*/
|
||||
public SenvenZExtractor(InputStream in, char[] password) {
|
||||
this(new SeekableInMemoryByteChannel(IoUtil.readBytes(in)), password);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param channel {@link SeekableByteChannel}
|
||||
*/
|
||||
public SenvenZExtractor(SeekableByteChannel channel) {
|
||||
this(channel, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param channel {@link SeekableByteChannel}
|
||||
* @param password 密码,null表示无密码
|
||||
*/
|
||||
public SenvenZExtractor(SeekableByteChannel channel, char[] password) {
|
||||
try {
|
||||
this.sevenZFile = new SevenZFile(channel, password);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放(解压)到指定目录,结束后自动关闭流,此方法只能调用一次
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
*/
|
||||
@Override
|
||||
public void extract(File targetDir, Filter<ArchiveEntry> filter) {
|
||||
try {
|
||||
extractInternal(targetDir, filter);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放(解压)到指定目录
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
private void extractInternal(File targetDir, 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;
|
||||
File outItemFile;
|
||||
while (null != (entry = this.sevenZFile.getNextEntry())) {
|
||||
outItemFile = FileUtil.file(targetDir, entry.getName());
|
||||
if (entry.isDirectory()) {
|
||||
// 创建对应目录
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outItemFile.mkdirs();
|
||||
} else if(entry.hasStream()){
|
||||
// 读取entry对应数据流
|
||||
FileUtil.writeFromStream(new Seven7EntryInputStream(sevenZFile, entry), outItemFile);
|
||||
} else {
|
||||
// 无数据流的文件创建为空文件
|
||||
FileUtil.touch(outItemFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IoUtil.close(this.sevenZFile);
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package cn.hutool.extra.compress.extractor;
|
||||
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 7z解压中文件流读取的封装
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.5.0
|
||||
*/
|
||||
public class Seven7EntryInputStream extends InputStream {
|
||||
|
||||
private final SevenZFile sevenZFile;
|
||||
private final long size;
|
||||
private long readSize = 0;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param sevenZFile {@link SevenZFile}
|
||||
* @param entry {@link SevenZArchiveEntry}
|
||||
*/
|
||||
public Seven7EntryInputStream(SevenZFile sevenZFile, SevenZArchiveEntry entry) {
|
||||
this.sevenZFile = sevenZFile;
|
||||
this.size = entry.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
try{
|
||||
return Math.toIntExact(this.size);
|
||||
} catch (ArithmeticException e){
|
||||
throw new IOException("Entry size is too large!(max than Integer.MAX)", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
this.readSize++;
|
||||
return this.sevenZFile.read();
|
||||
}
|
||||
}
|
@ -2,7 +2,10 @@ package cn.hutool.extra.compress.extractor;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.compress.CompressException;
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.ArchiveException;
|
||||
@ -14,29 +17,82 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class StreamExtractor {
|
||||
/**
|
||||
* 数据解压器,即将归档打包的数据释放
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.5.0
|
||||
*/
|
||||
public class StreamExtractor implements Extractor{
|
||||
|
||||
private final ArchiveInputStream in;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param charset 编码
|
||||
* @param file 包文件
|
||||
*/
|
||||
public StreamExtractor(Charset charset, File file) {
|
||||
this(charset, null, file);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param charset 编码
|
||||
* @param archiverName 归档包格式,null表示自动检测
|
||||
* @param file 包文件
|
||||
*/
|
||||
public StreamExtractor(Charset charset, String archiverName, File file) {
|
||||
this(charset, archiverName, FileUtil.getInputStream(file));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param charset 编码
|
||||
* @param in 包流
|
||||
*/
|
||||
public StreamExtractor(Charset charset, InputStream in) {
|
||||
this(charset, null, in);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param charset 编码
|
||||
* @param archiverName 归档包格式,null表示自动检测
|
||||
* @param in 包流
|
||||
*/
|
||||
public StreamExtractor(Charset charset, String archiverName, InputStream in) {
|
||||
final ArchiveStreamFactory factory = new ArchiveStreamFactory(charset.name());
|
||||
try {
|
||||
this.in = factory.createArchiveInputStream(in);
|
||||
in = IoUtil.toBuffered(in);
|
||||
if (StrUtil.isBlank(archiverName)) {
|
||||
this.in = factory.createArchiveInputStream(in);
|
||||
} else {
|
||||
this.in = factory.createArchiveInputStream(archiverName, in);
|
||||
}
|
||||
} catch (ArchiveException e) {
|
||||
throw new CompressException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放(解压)到指定目录
|
||||
* 释放(解压)到指定目录,结束后自动关闭流,此方法只能调用一次
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
*/
|
||||
public void extract(File targetDir) {
|
||||
@Override
|
||||
public void extract(File targetDir, Filter<ArchiveEntry> filter) {
|
||||
try {
|
||||
extractInternal(targetDir);
|
||||
extractInternal(targetDir, filter);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,20 +100,21 @@ public class StreamExtractor {
|
||||
* 释放(解压)到指定目录
|
||||
*
|
||||
* @param targetDir 目标目录
|
||||
* @param filter 解压文件过滤器,用于指定需要释放的文件,null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
private void extractInternal(File targetDir) throws IOException {
|
||||
Assert.isTrue(null != targetDir && targetDir.isDirectory(), "target must be dir.");
|
||||
private void extractInternal(File targetDir, 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;
|
||||
File outItemFile;
|
||||
while(null != (entry = this.in.getNextEntry())){
|
||||
if(false == in.canReadEntryData(entry)){
|
||||
while (null != (entry = in.getNextEntry())) {
|
||||
if (false == in.canReadEntryData(entry)) {
|
||||
// 无法读取的文件直接跳过
|
||||
continue;
|
||||
}
|
||||
outItemFile = FileUtil.file(targetDir, entry.getName());
|
||||
if(entry.isDirectory()){
|
||||
if (entry.isDirectory()) {
|
||||
// 创建对应目录
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outItemFile.mkdirs();
|
||||
@ -66,4 +123,9 @@ public class StreamExtractor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IoUtil.close(this.in);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,18 @@ import java.io.File;
|
||||
|
||||
public class ArchiverTest {
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void zipTest(){
|
||||
final File file = FileUtil.file("d:/test/compress/test.zip");
|
||||
StreamArchiver.create(CharsetUtil.CHARSET_UTF_8, ArchiveStreamFactory.ZIP, file)
|
||||
.add(FileUtil.file("d:/Java"), (f)->{
|
||||
Console.log("Add: {}", f.getPath());
|
||||
return true;
|
||||
})
|
||||
.finish().close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void tarTest(){
|
||||
@ -41,7 +53,7 @@ public class ArchiverTest {
|
||||
public void senvenZTest(){
|
||||
final File file = FileUtil.file("d:/test/compress/test.7z");
|
||||
CompressUtil.createArchiver(CharsetUtil.CHARSET_UTF_8, ArchiveStreamFactory.SEVEN_Z, file)
|
||||
.add(FileUtil.file("d:/Java"), (f)->{
|
||||
.add(FileUtil.file("d:/Java/apache-maven-3.6.3"), (f)->{
|
||||
Console.log("Add: {}", f.getPath());
|
||||
return true;
|
||||
})
|
||||
|
@ -0,0 +1,30 @@
|
||||
package cn.hutool.extra.compress;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.extra.compress.extractor.Extractor;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ExtractorTest {
|
||||
|
||||
@Test
|
||||
// @Ignore
|
||||
public void zipTest(){
|
||||
Extractor extractor = CompressUtil.createExtractor(
|
||||
CharsetUtil.defaultCharset(),
|
||||
FileUtil.file("d:/test/compress/test.zip"));
|
||||
|
||||
extractor.extract(FileUtil.file("d:/test/compress/test2/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void sevenZTest(){
|
||||
Extractor extractor = CompressUtil.createExtractor(
|
||||
CharsetUtil.defaultCharset(),
|
||||
FileUtil.file("d:/test/compress/test.7z"));
|
||||
|
||||
extractor.extract(FileUtil.file("d:/test/compress/test2/"));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user