This commit is contained in:
Looly
2022-06-18 23:03:06 +08:00
parent b0ed5bea9a
commit e9cf532af0
40 changed files with 327 additions and 415 deletions

View File

@@ -1,10 +1,10 @@
package cn.hutool.extra.compress.archiver;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import java.io.Closeable;
import java.io.File;
import java.util.function.Predicate;
/**
* 数据归档封装,归档即将几个文件或目录打成一个压缩包
@@ -27,11 +27,11 @@ public interface Archiver extends Closeable {
* 将文件或目录加入归档,目录采取递归读取方式按照层级加入
*
* @param file 文件或目录
* @param filter 文件过滤器,指定哪些文件或目录可以加入,{@link Filter#accept(Object)}为true时加入
* @param predicate 文件过滤器,指定哪些文件或目录可以加入,{@link Predicate#test(Object)}为{@code true}时加入null表示全部加入
* @return this
*/
default Archiver add(final File file, final Filter<File> filter) {
return add(file, StrUtil.SLASH, filter);
default Archiver add(final File file, final Predicate<File> predicate) {
return add(file, StrUtil.SLASH, predicate);
}
/**
@@ -39,10 +39,10 @@ public interface Archiver extends Closeable {
*
* @param file 文件或目录
* @param path 文件或目录的初始路径null表示位于根路径
* @param filter 文件过滤器,指定哪些文件或目录可以加入,{@link Filter#accept(Object)}为true时加入
* @param filter 文件过滤器,指定哪些文件或目录可以加入,{@link Predicate#test(Object)}为{@code true}保留null表示全部加入
* @return this
*/
Archiver add(File file, String path, Filter<File> filter);
Archiver add(File file, String path, Predicate<File> filter);
/**
* 结束已经增加的文件归档,此方法不会关闭归档流,可以继续添加文件

View File

@@ -3,9 +3,8 @@ 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.func.Filter;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
@@ -13,6 +12,7 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.channels.SeekableByteChannel;
import java.util.function.Predicate;
/**
* 7zip格式的归档封装
@@ -77,7 +77,7 @@ public class SevenZArchiver implements Archiver {
}
@Override
public SevenZArchiver add(final File file, final String path, final Filter<File> filter) {
public SevenZArchiver add(final File file, final String path, final Predicate<File> filter) {
try {
addInternal(file, path, filter);
} catch (final IOException e) {
@@ -118,19 +118,19 @@ public class SevenZArchiver implements Archiver {
*
* @param file 文件或目录
* @param path 文件或目录的初始路径null表示位于根路径
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link Filter#accept(Object)}为true时加入。
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link Predicate#test(Object)}为{@code true}保留null表示保留全部
*/
private void addInternal(final File file, final String path, final Filter<File> filter) throws IOException {
if (null != filter && false == filter.accept(file)) {
private void addInternal(final File file, final String path, final Predicate<File> filter) throws IOException {
if (null != filter && false == filter.test(file)) {
return;
}
final SevenZOutputFile out = this.sevenZOutputFile;
final String entryName;
if(StrUtil.isNotEmpty(path)){
if (StrUtil.isNotEmpty(path)) {
// 非空拼接路径格式为path/name
entryName = StrUtil.addSuffixIfNot(path, StrUtil.SLASH) + file.getName();
} else{
} else {
// 路径空直接使用文件名或目录名
entryName = file.getName();
}
@@ -139,7 +139,7 @@ public class SevenZArchiver implements Archiver {
if (file.isDirectory()) {
// 目录遍历写入
final File[] files = file.listFiles();
if(ArrayUtil.isNotEmpty(files)){
if (ArrayUtil.isNotEmpty(files)) {
for (final File childFile : files) {
addInternal(childFile, entryName, filter);
}

View File

@@ -3,9 +3,8 @@ 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.func.Filter;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.extra.compress.CompressException;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
@@ -17,6 +16,7 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.function.Predicate;
/**
* 数据归档封装,归档即将几个文件或目录打成一个压缩包<br>
@@ -86,26 +86,26 @@ public class StreamArchiver implements Archiver {
}
//特殊设置
if(this.out instanceof TarArchiveOutputStream){
((TarArchiveOutputStream)out).setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
} else if(this.out instanceof ArArchiveOutputStream){
((ArArchiveOutputStream)out).setLongFileMode(ArArchiveOutputStream.LONGFILE_BSD);
if (this.out instanceof TarArchiveOutputStream) {
((TarArchiveOutputStream) out).setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
} else if (this.out instanceof ArArchiveOutputStream) {
((ArArchiveOutputStream) out).setLongFileMode(ArArchiveOutputStream.LONGFILE_BSD);
}
}
/**
* 将文件或目录加入归档包,目录采取递归读取方式按照层级加入
*
* @param file 文件或目录
* @param path 文件或目录的初始路径null表示位于根路径
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link Filter#accept(Object)}为true加入
* @param file 文件或目录
* @param path 文件或目录的初始路径null表示位于根路径
* @param predicate 文件过滤器,指定哪些文件或目录可以加入,当{@link Predicate#test(Object)}为{@code true}加入null表示全部加入
* @return this
* @throws IORuntimeException IO异常
*/
@Override
public StreamArchiver add(final File file, final String path, final Filter<File> filter) throws IORuntimeException {
public StreamArchiver add(final File file, final String path, final Predicate<File> predicate) throws IORuntimeException {
try {
addInternal(file, path, filter);
addInternal(file, path, predicate);
} catch (final IOException e) {
throw new IORuntimeException(e);
}
@@ -140,21 +140,21 @@ public class StreamArchiver implements Archiver {
/**
* 将文件或目录加入归档包,目录采取递归读取方式按照层级加入
*
* @param file 文件或目录
* @param path 文件或目录的初始路径,{@code null}表示位于根路径
* @param filter 文件过滤器,指定哪些文件或目录可以加入,当{@link Filter#accept(Object)}为true加入。
* @param file 文件或目录
* @param path 文件或目录的初始路径,{@code null}表示位于根路径
* @param predicate 文件过滤器,指定哪些文件或目录可以加入,当{@link Predicate#test(Object)}为{@code true}加入。
*/
private void addInternal(final File file, final String path, final Filter<File> filter) throws IOException {
if (null != filter && false == filter.accept(file)) {
private void addInternal(final File file, final String path, final Predicate<File> predicate) throws IOException {
if (null != predicate && false == predicate.test(file)) {
return;
}
final ArchiveOutputStream out = this.out;
final String entryName;
if(StrUtil.isNotEmpty(path)){
if (StrUtil.isNotEmpty(path)) {
// 非空拼接路径格式为path/name
entryName = StrUtil.addSuffixIfNot(path, StrUtil.SLASH) + file.getName();
} else{
} else {
// 路径空直接使用文件名或目录名
entryName = file.getName();
}
@@ -163,9 +163,9 @@ public class StreamArchiver implements Archiver {
if (file.isDirectory()) {
// 目录遍历写入
final File[] files = file.listFiles();
if(ArrayUtil.isNotEmpty(files)){
if (ArrayUtil.isNotEmpty(files)) {
for (final File childFile : files) {
addInternal(childFile, entryName, filter);
addInternal(childFile, entryName, predicate);
}
}
} else {

View File

@@ -1,10 +1,10 @@
package cn.hutool.extra.compress.extractor;
import cn.hutool.core.lang.func.Filter;
import org.apache.commons.compress.archivers.ArchiveEntry;
import java.io.Closeable;
import java.io.File;
import java.util.function.Predicate;
/**
* 归档数据解包封装用于将zip、tar等包解包为文件
@@ -19,7 +19,7 @@ public interface Extractor extends Closeable {
*
* @param targetDir 目标目录
*/
default void extract(final File targetDir){
default void extract(final File targetDir) {
extract(targetDir, null);
}
@@ -27,9 +27,9 @@ public interface Extractor extends Closeable {
* 释放(解压)到指定目录,结束后自动关闭流,此方法只能调用一次
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器,用于指定需要释放的文件,{@code null}表示不过滤。{@link Filter#accept(Object)}为true时释放。
* @param predicate 解压文件过滤器,用于指定需要释放的文件,{@code null}表示不过滤。{@link Predicate#test(Object)}为{@code true}时释放。
*/
void extract(File targetDir, Filter<ArchiveEntry> filter);
void extract(File targetDir, Predicate<ArchiveEntry> predicate);
/**
* 无异常关闭

View File

@@ -4,7 +4,6 @@ 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.func.Filter;
import cn.hutool.core.text.StrUtil;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
@@ -16,6 +15,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.SeekableByteChannel;
import java.util.RandomAccess;
import java.util.function.Predicate;
/**
* 7z格式数据解压器即将归档打包的数据释放
@@ -30,7 +30,7 @@ public class SevenZExtractor implements Extractor, RandomAccess {
/**
* 构造
*
* @param file 包文件
* @param file 包文件
*/
public SevenZExtractor(final File file) {
this(file, null);
@@ -53,7 +53,7 @@ public class SevenZExtractor implements Extractor, RandomAccess {
/**
* 构造
*
* @param in 包流
* @param in 包流
*/
public SevenZExtractor(final InputStream in) {
this(in, null);
@@ -72,7 +72,7 @@ public class SevenZExtractor implements Extractor, RandomAccess {
/**
* 构造
*
* @param channel {@link SeekableByteChannel}
* @param channel {@link SeekableByteChannel}
*/
public SevenZExtractor(final SeekableByteChannel channel) {
this(channel, null);
@@ -92,16 +92,10 @@ public class SevenZExtractor implements Extractor, RandomAccess {
}
}
/**
* 释放(解压)到指定目录,结束后自动关闭流,此方法只能调用一次
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器用于指定需要释放的文件null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
*/
@Override
public void extract(final File targetDir, final Filter<ArchiveEntry> filter) {
public void extract(final File targetDir, final Predicate<ArchiveEntry> predicate) {
try {
extractInternal(targetDir, filter);
extractInternal(targetDir, predicate);
} catch (final IOException e) {
throw new IORuntimeException(e);
} finally {
@@ -112,17 +106,17 @@ public class SevenZExtractor implements Extractor, RandomAccess {
/**
* 获取满足指定过滤要求的压缩包内的第一个文件流
*
* @param filter 用于指定需要释放的文件null表示不过滤。当{@link Filter#accept(Object)}为true返回对应流。
* @return 满足过滤要求的第一个文件的流,无满足条件的文件返回{@code null}
* @param predicate 用于指定需要释放的文件null表示不过滤。当{@link Predicate#test(Object)}为{@code true}返回对应流。
* @return 满足过滤要求的第一个文件的流, 无满足条件的文件返回{@code null}
* @since 5.7.14
*/
public InputStream getFirst(final Filter<ArchiveEntry> filter) {
public InputStream getFirst(final Predicate<ArchiveEntry> predicate) {
final SevenZFile sevenZFile = this.sevenZFile;
for(final SevenZArchiveEntry entry : sevenZFile.getEntries()){
if(null != filter && false == filter.accept(entry)){
for (final SevenZArchiveEntry entry : sevenZFile.getEntries()) {
if (null != predicate && false == predicate.test(entry)) {
continue;
}
if(entry.isDirectory()){
if (entry.isDirectory()) {
continue;
}
@@ -143,24 +137,24 @@ public class SevenZExtractor implements Extractor, RandomAccess {
* @return 文件流,无文件返回{@code null}
* @since 5.7.14
*/
public InputStream get(final String entryName){
return getFirst((entry)-> StrUtil.equals(entryName, entry.getName()));
public InputStream get(final String entryName) {
return getFirst((entry) -> StrUtil.equals(entryName, entry.getName()));
}
/**
* 释放(解压)到指定目录
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器用于指定需要释放的文件null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
* @param predicate 解压文件过滤器用于指定需要释放的文件null表示不过滤。当{@link Predicate#test(Object)}为{@code true}时释放。
* @throws IOException IO异常
*/
private void extractInternal(final File targetDir, final Filter<ArchiveEntry> filter) throws IOException {
private void extractInternal(final File targetDir, final Predicate<ArchiveEntry> predicate) 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())) {
if(null != filter && false == filter.accept(entry)){
if (null != predicate && false == predicate.test(entry)) {
continue;
}
outItemFile = FileUtil.file(targetDir, entry.getName());
@@ -168,7 +162,7 @@ public class SevenZExtractor implements Extractor, RandomAccess {
// 创建对应目录
//noinspection ResultOfMethodCallIgnored
outItemFile.mkdirs();
} else if(entry.hasStream()){
} else if (entry.hasStream()) {
// 读取entry对应数据流
FileUtil.writeFromStream(new Seven7EntryInputStream(sevenZFile, entry), outItemFile);
} else {

View File

@@ -4,7 +4,6 @@ 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.func.Filter;
import cn.hutool.core.text.StrUtil;
import cn.hutool.extra.compress.CompressException;
import org.apache.commons.compress.archivers.ArchiveEntry;
@@ -16,6 +15,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.function.Predicate;
/**
* 数据解压器,即将归档打包的数据释放
@@ -23,15 +23,15 @@ import java.nio.charset.Charset;
* @author looly
* @since 5.5.0
*/
public class StreamExtractor implements Extractor{
public class StreamExtractor implements Extractor {
private final ArchiveInputStream in;
/**
* 构造
*
* @param charset 编码
* @param file 包文件
* @param charset 编码
* @param file 包文件
*/
public StreamExtractor(final Charset charset, final File file) {
this(charset, null, file);
@@ -85,12 +85,12 @@ public class StreamExtractor implements Extractor{
* 释放(解压)到指定目录,结束后自动关闭流,此方法只能调用一次
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器用于指定需要释放的文件null表示不过滤。当{@link Filter#accept(Object)}为true时释放。
* @param predicate 解压文件过滤器用于指定需要释放的文件null表示不过滤。当{@link Predicate#test(Object)}为{@code true}时释放。
*/
@Override
public void extract(final File targetDir, final Filter<ArchiveEntry> filter) {
public void extract(final File targetDir, final Predicate<ArchiveEntry> predicate) {
try {
extractInternal(targetDir, filter);
extractInternal(targetDir, predicate);
} catch (final IOException e) {
throw new IORuntimeException(e);
} finally {
@@ -102,16 +102,16 @@ public class StreamExtractor implements Extractor{
* 释放(解压)到指定目录
*
* @param targetDir 目标目录
* @param filter 解压文件过滤器用于指定需要释放的文件null表示不过滤。当{@link Filter#accept(Object)}为true释放。
* @param predicate 解压文件过滤器用于指定需要释放的文件null表示不过滤。当{@link Predicate#test(Object)}为{@code true}释放。
* @throws IOException IO异常
*/
private void extractInternal(final File targetDir, final Filter<ArchiveEntry> filter) throws IOException {
private void extractInternal(final File targetDir, final Predicate<ArchiveEntry> predicate) 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 = in.getNextEntry())) {
if(null != filter && false == filter.accept(entry)){
if (null != predicate && false == predicate.test(entry)) {
continue;
}
if (false == in.canReadEntryData(entry)) {

View File

@@ -4,10 +4,9 @@ import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.text.StrUtil;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
@@ -21,6 +20,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
/**
* FTP客户端封装<br>
@@ -340,11 +340,11 @@ public class Ftp extends AbstractFtp {
* 此方法自动过滤"."和".."两种目录
*
* @param path 目录
* @param filter 过滤器null表示不过滤默认去掉"."和".."两种目录
* @param predicate 过滤器null表示不过滤默认去掉"."和".."两种目录
* @return 文件或目录列表
* @since 5.3.5
*/
public List<FTPFile> lsFiles(final String path, final Filter<FTPFile> filter) {
public List<FTPFile> lsFiles(final String path, final Predicate<FTPFile> predicate) {
final FTPFile[] ftpFiles = lsFiles(path);
if (ArrayUtil.isEmpty(ftpFiles)) {
return ListUtil.empty();
@@ -355,7 +355,7 @@ public class Ftp extends AbstractFtp {
for (final FTPFile ftpFile : ftpFiles) {
fileName = ftpFile.getName();
if (false == StrUtil.equals(".", fileName) && false == StrUtil.equals("..", fileName)) {
if (null == filter || filter.accept(ftpFile)) {
if (null == predicate || predicate.test(ftpFile)) {
result.add(ftpFile);
}
}

View File

@@ -3,7 +3,6 @@ package cn.hutool.extra.ssh;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.func.Filter;
import cn.hutool.core.text.StrUtil;
import cn.hutool.extra.ftp.AbstractFtp;
import cn.hutool.extra.ftp.FtpConfig;
@@ -23,6 +22,7 @@ import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.function.Predicate;
/**
* SFTP是Secure File Transfer Protocol的缩写安全文件传送协议。可以为传输文件提供一种安全的加密方法。<br>
@@ -302,13 +302,13 @@ public class Sftp extends AbstractFtp {
* 遍历某个目录下所有文件或目录,不会递归遍历<br>
* 此方法自动过滤"."和".."两种目录
*
* @param path 遍历某个目录下所有文件或目录
* @param filter 文件或目录过滤器,可以实现过滤器返回自己需要的文件或目录名列表
* @param path 遍历某个目录下所有文件或目录
* @param predicate 文件或目录过滤器,可以实现过滤器返回自己需要的文件或目录名列表{@link Predicate#test(Object)}为{@code true}保留
* @return 目录或文件名列表
* @since 4.0.5
*/
public List<String> ls(final String path, final Filter<LsEntry> filter) {
final List<LsEntry> entries = lsEntries(path, filter);
public List<String> ls(final String path, final Predicate<LsEntry> predicate) {
final List<LsEntry> entries = lsEntries(path, predicate);
if (CollUtil.isEmpty(entries)) {
return ListUtil.empty();
}
@@ -331,18 +331,18 @@ public class Sftp extends AbstractFtp {
* 遍历某个目录下所有文件或目录生成LsEntry列表不会递归遍历<br>
* 此方法自动过滤"."和".."两种目录
*
* @param path 遍历某个目录下所有文件或目录
* @param filter 文件或目录过滤器,可以实现过滤器返回自己需要的文件或目录名列表
* @param path 遍历某个目录下所有文件或目录
* @param predicate 文件或目录过滤器,可以实现过滤器返回自己需要的文件或目录名列表{@link Predicate#test(Object)}为{@code true}保留
* @return 目录或文件名列表
* @since 5.3.5
*/
public List<LsEntry> lsEntries(final String path, final Filter<LsEntry> filter) {
public List<LsEntry> lsEntries(final String path, final Predicate<LsEntry> predicate) {
final List<LsEntry> entryList = new ArrayList<>();
try {
channel.ls(path, entry -> {
final String fileName = entry.getFilename();
if (false == StrUtil.equals(".", fileName) && false == StrUtil.equals("..", fileName)) {
if (null == filter || filter.accept(entry)) {
if (null == predicate || predicate.test(entry)) {
entryList.add(entry);
}
}