mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add cpmpress
This commit is contained in:
parent
5154799ee8
commit
9acc216f90
@ -8,6 +8,7 @@
|
||||
### 🐣新特性
|
||||
* 【core 】 MapProxy支持return this的setter方法(pr#392@Gitee)
|
||||
* 【core 】 BeeDSFactory移除sqlite事务修复代码,新版本BeeCP已修复
|
||||
* 【core 】 增加compress包,扩充Zip操作灵活性
|
||||
|
||||
### 🐞Bug修复
|
||||
|
||||
|
98
hutool-core/src/main/java/cn/hutool/core/compress/Deflate.java
Executable file
98
hutool-core/src/main/java/cn/hutool/core/compress/Deflate.java
Executable file
@ -0,0 +1,98 @@
|
||||
package cn.hutool.core.compress;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterOutputStream;
|
||||
|
||||
/**
|
||||
* Deflate算法<br>
|
||||
* Deflate是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public class Deflate implements Closeable {
|
||||
|
||||
private final InputStream source;
|
||||
private OutputStream target;
|
||||
private final boolean nowrap;
|
||||
|
||||
/**
|
||||
* 创建Deflate
|
||||
*
|
||||
* @param source 源流
|
||||
* @param target 目标流
|
||||
* @param nowrap {@code true}表示兼容Gzip压缩
|
||||
*/
|
||||
public static Deflate of(InputStream source, OutputStream target, boolean nowrap) {
|
||||
return new Deflate(source, target, nowrap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param source 源流
|
||||
* @param target 目标流
|
||||
* @param nowrap {@code true}表示兼容Gzip压缩
|
||||
*/
|
||||
public Deflate(InputStream source, OutputStream target, boolean nowrap) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
this.nowrap = nowrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取目标流
|
||||
*
|
||||
* @return 目标流
|
||||
*/
|
||||
public OutputStream getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将普通数据流压缩
|
||||
*
|
||||
* @param level 压缩级别,0~9
|
||||
*/
|
||||
public Deflate deflater(int level) {
|
||||
target= (target instanceof DeflaterOutputStream) ?
|
||||
(DeflaterOutputStream) target : new DeflaterOutputStream(target, new Deflater(level, nowrap));
|
||||
IoUtil.copy(source, target);
|
||||
try {
|
||||
((DeflaterOutputStream)target).finish();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将压缩流解压到target中
|
||||
*/
|
||||
public Deflate inflater() {
|
||||
target = (target instanceof InflaterOutputStream) ?
|
||||
(InflaterOutputStream) target : new InflaterOutputStream(target, new Inflater(nowrap));
|
||||
IoUtil.copy(source, target);
|
||||
try {
|
||||
((InflaterOutputStream)target).finish();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IoUtil.close(this.target);
|
||||
IoUtil.close(this.source);
|
||||
}
|
||||
}
|
89
hutool-core/src/main/java/cn/hutool/core/compress/Gzip.java
Executable file
89
hutool-core/src/main/java/cn/hutool/core/compress/Gzip.java
Executable file
@ -0,0 +1,89 @@
|
||||
package cn.hutool.core.compress;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* GZIP是用于Unix系统的文件压缩<br>
|
||||
* gzip的基础是DEFLATE
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public class Gzip implements Closeable {
|
||||
|
||||
private InputStream source;
|
||||
private OutputStream target;
|
||||
|
||||
/**
|
||||
* 创建Gzip
|
||||
*
|
||||
* @param source 源流
|
||||
* @param target 目标流
|
||||
*/
|
||||
public static Gzip of(InputStream source, OutputStream target) {
|
||||
return new Gzip(source, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param source 源流
|
||||
* @param target 目标流
|
||||
*/
|
||||
public Gzip(InputStream source, OutputStream target) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取目标流
|
||||
*
|
||||
* @return 目标流
|
||||
*/
|
||||
public OutputStream getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将普通数据流压缩
|
||||
*/
|
||||
public Gzip gzip() {
|
||||
try {
|
||||
target = (target instanceof GZIPOutputStream) ?
|
||||
(GZIPOutputStream) target : new GZIPOutputStream(target);
|
||||
IoUtil.copy(source, target);
|
||||
((GZIPOutputStream)target).finish();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将压缩流解压到target中
|
||||
*/
|
||||
public Gzip unGzip() {
|
||||
try {
|
||||
source = (source instanceof GZIPInputStream) ?
|
||||
(GZIPInputStream) source : new GZIPInputStream(source);
|
||||
IoUtil.copy(source, target);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IoUtil.close(this.target);
|
||||
IoUtil.close(this.source);
|
||||
}
|
||||
}
|
189
hutool-core/src/main/java/cn/hutool/core/compress/ZipReader.java
Executable file
189
hutool-core/src/main/java/cn/hutool/core/compress/ZipReader.java
Executable file
@ -0,0 +1,189 @@
|
||||
package cn.hutool.core.compress;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Enumeration;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* Zip文件或流读取器,一般用于Zip文件解压
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public class ZipReader implements Closeable {
|
||||
|
||||
private ZipFile zipFile;
|
||||
private ZipInputStream in;
|
||||
|
||||
/**
|
||||
* 创建{@link ZipReader}
|
||||
*
|
||||
* @param zipFile 生成的Zip文件
|
||||
* @param charset 编码
|
||||
* @return {@link ZipReader}
|
||||
*/
|
||||
public static ZipReader of(File zipFile, Charset charset) {
|
||||
return new ZipReader(zipFile, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建{@link ZipReader}
|
||||
*
|
||||
* @param in Zip输入的流,一般为输入文件流
|
||||
* @param charset 编码
|
||||
* @return {@link ZipReader}
|
||||
*/
|
||||
public static ZipReader of(InputStream in, Charset charset) {
|
||||
return new ZipReader(in, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param zipFile 读取的的Zip文件
|
||||
*/
|
||||
public ZipReader(File zipFile, Charset charset) {
|
||||
this.zipFile = ZipUtil.toZipFile(zipFile, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param zipFile 读取的的Zip文件
|
||||
*/
|
||||
public ZipReader(ZipFile zipFile) {
|
||||
this.zipFile = zipFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param in 读取的的Zip文件流
|
||||
*/
|
||||
public ZipReader(InputStream in, Charset charset) {
|
||||
this.in = new ZipInputStream(in, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param zin 读取的的Zip文件流
|
||||
*/
|
||||
public ZipReader(ZipInputStream zin) {
|
||||
this.in = zin;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定路径的文件流
|
||||
*
|
||||
* @param path 路径
|
||||
* @return 文件流
|
||||
*/
|
||||
public InputStream get(String path) {
|
||||
if (null != this.zipFile) {
|
||||
final ZipFile zipFile = this.zipFile;
|
||||
final ZipEntry entry = zipFile.getEntry(path);
|
||||
if (null != entry) {
|
||||
return ZipUtil.getStream(zipFile, entry);
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Zip stream mode not support get!");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解压到指定目录中
|
||||
*
|
||||
* @param outFile 解压到的目录
|
||||
* @return 解压的目录
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public File readTo(File outFile) throws IORuntimeException {
|
||||
read((zipEntry) -> {
|
||||
// FileUtil.file会检查slip漏洞,漏洞说明见http://blog.nsfocus.net/zip-slip-2/
|
||||
File outItemFile = FileUtil.file(outFile, zipEntry.getName());
|
||||
if (zipEntry.isDirectory()) {
|
||||
// 目录
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outItemFile.mkdirs();
|
||||
} else {
|
||||
InputStream in;
|
||||
if (null != this.zipFile) {
|
||||
in = ZipUtil.getStream(this.zipFile, zipEntry);
|
||||
} else {
|
||||
in = this.in;
|
||||
}
|
||||
// 文件
|
||||
FileUtil.writeFromStream(in, outItemFile, false);
|
||||
}
|
||||
});
|
||||
return outFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取并处理Zip文件中的每一个{@link ZipEntry}
|
||||
*
|
||||
* @param consumer {@link ZipEntry}处理器
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public ZipReader read(Consumer<ZipEntry> consumer) throws IORuntimeException {
|
||||
if (null != this.zipFile) {
|
||||
readFromZipFile(consumer);
|
||||
} else {
|
||||
readFromStream(consumer);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IORuntimeException {
|
||||
if(null != this.zipFile){
|
||||
IoUtil.close(this.zipFile);
|
||||
} else {
|
||||
IoUtil.close(this.in);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取并处理Zip文件中的每一个{@link ZipEntry}
|
||||
*
|
||||
* @param consumer {@link ZipEntry}处理器
|
||||
*/
|
||||
private void readFromZipFile(Consumer<ZipEntry> consumer) {
|
||||
final Enumeration<? extends ZipEntry> em = zipFile.entries();
|
||||
while (em.hasMoreElements()) {
|
||||
consumer.accept(em.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取并处理Zip流中的每一个{@link ZipEntry}
|
||||
*
|
||||
* @param consumer {@link ZipEntry}处理器
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
private void readFromStream(Consumer<ZipEntry> consumer) throws IORuntimeException {
|
||||
try {
|
||||
ZipEntry zipEntry;
|
||||
while (null != (zipEntry = in.getNextEntry())) {
|
||||
consumer.accept(zipEntry);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
270
hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java
Executable file
270
hutool-core/src/main/java/cn/hutool/core/compress/ZipWriter.java
Executable file
@ -0,0 +1,270 @@
|
||||
package cn.hutool.core.compress;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.io.resource.Resource;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* Zip生成封装
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public class ZipWriter implements Closeable {
|
||||
|
||||
/**
|
||||
* 创建{@link ZipWriter}
|
||||
*
|
||||
* @param zipFile 生成的Zip文件
|
||||
* @param charset 编码
|
||||
* @return {@link ZipWriter}
|
||||
*/
|
||||
public static ZipWriter of(File zipFile, Charset charset) {
|
||||
return new ZipWriter(zipFile, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建{@link ZipWriter}
|
||||
*
|
||||
* @param out Zip输出的流,一般为输出文件流
|
||||
* @param charset 编码
|
||||
* @return {@link ZipWriter}
|
||||
*/
|
||||
public static ZipWriter of(OutputStream out, Charset charset) {
|
||||
return new ZipWriter(out, charset);
|
||||
}
|
||||
|
||||
private final ZipOutputStream out;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param zipFile 生成的Zip文件
|
||||
*/
|
||||
public ZipWriter(File zipFile, Charset charset) {
|
||||
this.out = getZipOutputStream(zipFile, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param out {@link ZipOutputStream}
|
||||
*/
|
||||
public ZipWriter(OutputStream out, Charset charset) {
|
||||
this.out = getZipOutputStream(out, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param out {@link ZipOutputStream}
|
||||
*/
|
||||
public ZipWriter(ZipOutputStream out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置压缩级别,可选1~9,-1表示默认
|
||||
*
|
||||
* @param level 压缩级别
|
||||
* @return this
|
||||
*/
|
||||
public ZipWriter setLevel(int level) {
|
||||
this.out.setLevel(level);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置注释
|
||||
*
|
||||
* @param comment 注释
|
||||
* @return this
|
||||
*/
|
||||
public ZipWriter setComment(String comment) {
|
||||
this.out.setComment(comment);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取原始的{@link ZipOutputStream}
|
||||
*
|
||||
* @return {@link ZipOutputStream}
|
||||
*/
|
||||
public ZipOutputStream getOut() {
|
||||
return this.out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对文件或文件目录进行压缩
|
||||
*
|
||||
* @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩
|
||||
* @param filter 文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩),{@code null}表示不过滤
|
||||
* @param files 要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
|
||||
* @throws IORuntimeException IO异常
|
||||
* @since 5.1.1
|
||||
*/
|
||||
public ZipWriter add(boolean withSrcDir, FileFilter filter, File... files) throws IORuntimeException {
|
||||
for (File file : files) {
|
||||
// 如果只是压缩一个文件,则需要截取该文件的父目录
|
||||
String srcRootDir;
|
||||
try {
|
||||
srcRootDir = file.getCanonicalPath();
|
||||
if ((false == file.isDirectory()) || withSrcDir) {
|
||||
// 若是文件,则将父目录完整路径都截取掉;若设置包含目录,则将上级目录全部截取掉,保留本目录名
|
||||
srcRootDir = file.getCanonicalFile().getParentFile().getCanonicalPath();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
|
||||
_add(file, srcRootDir, filter);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加资源到压缩包,添加后关闭资源流
|
||||
*
|
||||
* @param resources 需要压缩的资源,资源的路径为{@link Resource#getName()}
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public ZipWriter add(Resource... resources) throws IORuntimeException {
|
||||
for (Resource resource : resources) {
|
||||
if (null != resource) {
|
||||
add(resource.getName(), resource.getStream());
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文件流到压缩包,添加后关闭输入文件流<br>
|
||||
* 如果输入流为{@code null},则只创建空目录
|
||||
*
|
||||
* @param path 压缩的路径, {@code null}和""表示根目录下
|
||||
* @param in 需要压缩的输入流,使用完后自动关闭,{@code null}表示加入空目录
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public ZipWriter add(String path, InputStream in) throws IORuntimeException {
|
||||
path = StrUtil.nullToEmpty(path);
|
||||
if (null == in) {
|
||||
// 空目录需要检查路径规范性,目录以"/"结尾
|
||||
path = StrUtil.addSuffixIfNot(path, StrUtil.SLASH);
|
||||
if (StrUtil.isBlank(path)) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
return putEntry(path, in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IORuntimeException {
|
||||
try {
|
||||
out.finish();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
IoUtil.close(this.out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得 {@link ZipOutputStream}
|
||||
*
|
||||
* @param zipFile 压缩文件
|
||||
* @param charset 编码
|
||||
* @return {@link ZipOutputStream}
|
||||
*/
|
||||
private static ZipOutputStream getZipOutputStream(File zipFile, Charset charset) {
|
||||
return getZipOutputStream(FileUtil.getOutputStream(zipFile), charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得 {@link ZipOutputStream}
|
||||
*
|
||||
* @param out 压缩文件流
|
||||
* @param charset 编码
|
||||
* @return {@link ZipOutputStream}
|
||||
*/
|
||||
private static ZipOutputStream getZipOutputStream(OutputStream out, Charset charset) {
|
||||
if (out instanceof ZipOutputStream) {
|
||||
return (ZipOutputStream) out;
|
||||
}
|
||||
return new ZipOutputStream(out, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归压缩文件夹或压缩文件<br>
|
||||
* srcRootDir决定了路径截取的位置,例如:<br>
|
||||
* file的路径为d:/a/b/c/d.txt,srcRootDir为d:/a/b,则压缩后的文件与目录为结构为c/d.txt
|
||||
*
|
||||
* @param srcRootDir 被压缩的文件夹根目录
|
||||
* @param file 当前递归压缩的文件或目录对象
|
||||
* @param filter 文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩),{@code null}表示不过滤
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
private ZipWriter _add(File file, String srcRootDir, FileFilter filter) throws IORuntimeException {
|
||||
if (null == file || (null != filter && false == filter.accept(file))) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// 获取文件相对于压缩文件夹根目录的子路径
|
||||
final String subPath = FileUtil.subPath(srcRootDir, file);
|
||||
if (file.isDirectory()) {
|
||||
// 如果是目录,则压缩压缩目录中的文件或子目录
|
||||
final File[] files = file.listFiles();
|
||||
if (ArrayUtil.isEmpty(files)) {
|
||||
// 加入目录,只有空目录时才加入目录,非空时会在创建文件时自动添加父级目录
|
||||
add(subPath, null);
|
||||
} else {
|
||||
// 压缩目录下的子文件或目录
|
||||
for (File childFile : files) {
|
||||
_add(childFile, srcRootDir, filter);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 如果是文件或其它符号,则直接压缩该文件
|
||||
putEntry(subPath, FileUtil.getInputStream(file));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文件流到压缩包,添加后关闭输入文件流<br>
|
||||
* 如果输入流为{@code null},则只创建空目录
|
||||
*
|
||||
* @param path 压缩的路径, {@code null}和""表示根目录下
|
||||
* @param in 需要压缩的输入流,使用完后自动关闭,{@code null}表示加入空目录
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
private ZipWriter putEntry(String path, InputStream in) throws IORuntimeException {
|
||||
try {
|
||||
out.putNextEntry(new ZipEntry(path));
|
||||
if (null != in) {
|
||||
IoUtil.copy(in, out);
|
||||
}
|
||||
out.closeEntry();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
IoUtil.close(in);
|
||||
}
|
||||
|
||||
IoUtil.flush(this.out);
|
||||
return this;
|
||||
}
|
||||
}
|
7
hutool-core/src/main/java/cn/hutool/core/compress/package-info.java
Executable file
7
hutool-core/src/main/java/cn/hutool/core/compress/package-info.java
Executable file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 压缩解压封装
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
package cn.hutool.core.compress;
|
@ -1,5 +1,9 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import cn.hutool.core.compress.Deflate;
|
||||
import cn.hutool.core.compress.Gzip;
|
||||
import cn.hutool.core.compress.ZipReader;
|
||||
import cn.hutool.core.compress.ZipWriter;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.io.FastByteArrayOutputStream;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
@ -18,15 +22,8 @@ import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterOutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
@ -35,6 +32,7 @@ import java.util.zip.ZipOutputStream;
|
||||
/**
|
||||
* 压缩工具类
|
||||
*
|
||||
* @see cn.hutool.core.compress.ZipWriter
|
||||
* @author Looly
|
||||
*/
|
||||
public class ZipUtil {
|
||||
@ -210,13 +208,7 @@ public class ZipUtil {
|
||||
*/
|
||||
public static File zip(File zipFile, Charset charset, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException {
|
||||
validateFiles(zipFile, srcFiles);
|
||||
|
||||
try (ZipOutputStream out = getZipOutputStream(zipFile, charset)) {
|
||||
zip(out, charset, withSrcDir, filter, srcFiles);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
|
||||
ZipWriter.of(zipFile, charset).add(withSrcDir, filter, srcFiles).close();
|
||||
return zipFile;
|
||||
}
|
||||
|
||||
@ -232,7 +224,7 @@ public class ZipUtil {
|
||||
* @since 5.1.1
|
||||
*/
|
||||
public static void zip(OutputStream out, Charset charset, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException {
|
||||
zip(getZipOutputStream(out, charset), withSrcDir, filter, srcFiles);
|
||||
ZipWriter.of(out, charset).add(withSrcDir, filter, srcFiles).close();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -244,27 +236,12 @@ public class ZipUtil {
|
||||
* @param srcFiles 要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
|
||||
* @throws IORuntimeException IO异常
|
||||
* @since 5.1.1
|
||||
* @deprecated 请使用 {@link #zip(OutputStream, Charset, boolean, FileFilter, File...)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static void zip(ZipOutputStream zipOutputStream, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException {
|
||||
String srcRootDir;
|
||||
try {
|
||||
for (File srcFile : srcFiles) {
|
||||
if (null == srcFile) {
|
||||
continue;
|
||||
}
|
||||
// 如果只是压缩一个文件,则需要截取该文件的父目录
|
||||
srcRootDir = srcFile.getCanonicalPath();
|
||||
if (srcFile.isFile() || withSrcDir) {
|
||||
// 若是文件,则将父目录完整路径都截取掉;若设置包含目录,则将上级目录全部截取掉,保留本目录名
|
||||
srcRootDir = srcFile.getCanonicalFile().getParentFile().getCanonicalPath();
|
||||
}
|
||||
// 调用递归压缩方法进行目录或文件压缩
|
||||
zip(srcFile, srcRootDir, zipOutputStream, filter);
|
||||
zipOutputStream.flush();
|
||||
}
|
||||
zipOutputStream.finish();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
try(final ZipWriter zipWriter = new ZipWriter(zipOutputStream)){
|
||||
zipWriter.add(withSrcDir, filter, srcFiles);
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,13 +332,19 @@ public class ZipUtil {
|
||||
* @since 3.0.9
|
||||
*/
|
||||
public static File zip(File zipFile, String[] paths, InputStream[] ins, Charset charset) throws UtilException {
|
||||
ZipOutputStream out = null;
|
||||
try {
|
||||
out = getZipOutputStream(zipFile, charset);
|
||||
zip(out, paths, ins);
|
||||
} finally {
|
||||
IoUtil.close(out);
|
||||
if (ArrayUtil.isEmpty(paths) || ArrayUtil.isEmpty(ins)) {
|
||||
throw new IllegalArgumentException("Paths or ins is empty !");
|
||||
}
|
||||
if (paths.length != ins.length) {
|
||||
throw new IllegalArgumentException("Paths length is not equals to ins length !");
|
||||
}
|
||||
|
||||
try(final ZipWriter zipWriter = ZipWriter.of(zipFile, charset)){
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
zipWriter.add(paths[i], ins[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return zipFile;
|
||||
}
|
||||
|
||||
@ -374,12 +357,17 @@ public class ZipUtil {
|
||||
* @since 5.5.2
|
||||
*/
|
||||
public static void zip(OutputStream out, String[] paths, InputStream[] ins) {
|
||||
ZipOutputStream zipOutputStream = null;
|
||||
try {
|
||||
zipOutputStream = getZipOutputStream(out, DEFAULT_CHARSET);
|
||||
zip(zipOutputStream, paths, ins);
|
||||
} finally {
|
||||
IoUtil.close(zipOutputStream);
|
||||
if (ArrayUtil.isEmpty(paths) || ArrayUtil.isEmpty(ins)) {
|
||||
throw new IllegalArgumentException("Paths or ins is empty !");
|
||||
}
|
||||
if (paths.length != ins.length) {
|
||||
throw new IllegalArgumentException("Paths length is not equals to ins length !");
|
||||
}
|
||||
|
||||
try(final ZipWriter zipWriter = ZipWriter.of(out, DEFAULT_CHARSET)){
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
zipWriter.add(paths[i], ins[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,8 +387,11 @@ public class ZipUtil {
|
||||
if (paths.length != ins.length) {
|
||||
throw new IllegalArgumentException("Paths length is not equals to ins length !");
|
||||
}
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
add(ins[i], paths[i], zipOutputStream);
|
||||
|
||||
try(final ZipWriter zipWriter = new ZipWriter(zipOutputStream)){
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
zipWriter.add(paths[i], ins[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,15 +407,7 @@ public class ZipUtil {
|
||||
* @since 5.5.2
|
||||
*/
|
||||
public static File zip(File zipFile, Charset charset, Resource... resources) throws UtilException {
|
||||
ZipOutputStream out = null;
|
||||
try {
|
||||
out = getZipOutputStream(zipFile, charset);
|
||||
for (Resource resource : resources) {
|
||||
add(resource.getStream(), resource.getName(), out);
|
||||
}
|
||||
} finally {
|
||||
IoUtil.close(out);
|
||||
}
|
||||
ZipWriter.of(zipFile, charset).add(resources).close();
|
||||
return zipFile;
|
||||
}
|
||||
|
||||
@ -541,21 +524,13 @@ public class ZipUtil {
|
||||
*/
|
||||
public static File unzip(ZipFile zipFile, File outFile) throws IORuntimeException {
|
||||
if (outFile.exists() && outFile.isFile()) {
|
||||
throw new UtilException("Target path [{}] exist!", outFile.getAbsolutePath());
|
||||
throw new IllegalArgumentException(
|
||||
StrUtil.format("Target path [{}] exist!", outFile.getAbsolutePath()));
|
||||
}
|
||||
read(zipFile, (zipEntry) -> {
|
||||
// FileUtil.file会检查slip漏洞,漏洞说明见http://blog.nsfocus.net/zip-slip-2/
|
||||
File outItemFile = FileUtil.file(outFile, zipEntry.getName());
|
||||
if (zipEntry.isDirectory()) {
|
||||
// 创建对应目录
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outItemFile.mkdirs();
|
||||
} else {
|
||||
// 写出文件
|
||||
write(zipFile, zipEntry, outItemFile);
|
||||
}
|
||||
});
|
||||
|
||||
try(final ZipReader reader = new ZipReader(zipFile)){
|
||||
reader.readTo(outFile);
|
||||
}
|
||||
return outFile;
|
||||
}
|
||||
|
||||
@ -596,13 +571,8 @@ public class ZipUtil {
|
||||
* @since 5.5.2
|
||||
*/
|
||||
public static void read(ZipFile zipFile, Consumer<ZipEntry> consumer) {
|
||||
try {
|
||||
final Enumeration<? extends ZipEntry> em = zipFile.entries();
|
||||
while (em.hasMoreElements()) {
|
||||
consumer.accept(em.nextElement());
|
||||
}
|
||||
} finally {
|
||||
IoUtil.close(zipFile);
|
||||
try(final ZipReader reader = new ZipReader(zipFile)){
|
||||
reader.read(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,18 +605,9 @@ public class ZipUtil {
|
||||
* @since 4.5.8
|
||||
*/
|
||||
public static File unzip(ZipInputStream zipStream, File outFile) throws UtilException {
|
||||
read(zipStream, (zipEntry) -> {
|
||||
// FileUtil.file会检查slip漏洞,漏洞说明见http://blog.nsfocus.net/zip-slip-2/
|
||||
File outItemFile = FileUtil.file(outFile, zipEntry.getName());
|
||||
if (zipEntry.isDirectory()) {
|
||||
// 目录
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outItemFile.mkdirs();
|
||||
} else {
|
||||
// 文件
|
||||
FileUtil.writeFromStream(zipStream, outItemFile, false);
|
||||
}
|
||||
});
|
||||
try(final ZipReader reader = new ZipReader(zipStream)){
|
||||
reader.readTo(outFile);
|
||||
}
|
||||
return outFile;
|
||||
}
|
||||
|
||||
@ -658,15 +619,8 @@ public class ZipUtil {
|
||||
* @since 5.5.2
|
||||
*/
|
||||
public static void read(ZipInputStream zipStream, Consumer<ZipEntry> consumer) {
|
||||
try {
|
||||
ZipEntry zipEntry;
|
||||
while (null != (zipEntry = zipStream.getNextEntry())) {
|
||||
consumer.accept(zipEntry);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UtilException(e);
|
||||
} finally {
|
||||
IoUtil.close(zipStream);
|
||||
try(final ZipReader reader = new ZipReader(zipStream)){
|
||||
reader.read(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -716,23 +670,10 @@ public class ZipUtil {
|
||||
* @return 文件内容bytes
|
||||
* @since 4.1.8
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static byte[] unzipFileBytes(File zipFile, Charset charset, String name) {
|
||||
ZipFile zipFileObj = null;
|
||||
try {
|
||||
zipFileObj = toZipFile(zipFile, charset);
|
||||
final Enumeration<ZipEntry> em = (Enumeration<ZipEntry>) zipFileObj.entries();
|
||||
ZipEntry zipEntry;
|
||||
while (em.hasMoreElements()) {
|
||||
zipEntry = em.nextElement();
|
||||
if ((false == zipEntry.isDirectory()) && name.equals(zipEntry.getName())) {
|
||||
return IoUtil.readBytes(getStream(zipFileObj, zipEntry));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
IoUtil.close(zipFileObj);
|
||||
try(final ZipReader reader = ZipReader.of(zipFile, charset)){
|
||||
return IoUtil.readBytes(reader.get(name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- Gzip
|
||||
@ -800,16 +741,7 @@ public class ZipUtil {
|
||||
*/
|
||||
public static byte[] gzip(InputStream in, int length) throws UtilException {
|
||||
final ByteArrayOutputStream bos = new ByteArrayOutputStream(length);
|
||||
GZIPOutputStream gos = null;
|
||||
try {
|
||||
gos = new GZIPOutputStream(bos);
|
||||
IoUtil.copy(in, gos);
|
||||
} catch (IOException e) {
|
||||
throw new UtilException(e);
|
||||
} finally {
|
||||
IoUtil.close(gos);
|
||||
}
|
||||
// 返回必须在关闭gos后进行,因为关闭时会自动执行finish()方法,保证数据全部写出
|
||||
Gzip.of(in, bos).gzip().close();
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
@ -857,18 +789,8 @@ public class ZipUtil {
|
||||
* @since 4.1.18
|
||||
*/
|
||||
public static byte[] unGzip(InputStream in, int length) throws UtilException {
|
||||
GZIPInputStream gzi = null;
|
||||
FastByteArrayOutputStream bos;
|
||||
try {
|
||||
gzi = (in instanceof GZIPInputStream) ? (GZIPInputStream) in : new GZIPInputStream(in);
|
||||
bos = new FastByteArrayOutputStream(length);
|
||||
IoUtil.copy(gzi, bos);
|
||||
} catch (IOException e) {
|
||||
throw new UtilException(e);
|
||||
} finally {
|
||||
IoUtil.close(gzi);
|
||||
}
|
||||
// 返回必须在关闭gos后进行,因为关闭时会自动执行finish()方法,保证数据全部写出
|
||||
FastByteArrayOutputStream bos = new FastByteArrayOutputStream(length);
|
||||
Gzip.of(in, bos).unGzip().close();
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
@ -940,7 +862,7 @@ public class ZipUtil {
|
||||
*/
|
||||
public static byte[] zlib(InputStream in, int level, int length) {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream(length);
|
||||
deflater(in, out, level, false);
|
||||
Deflate.of(in, out, false).deflater(level);
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
@ -988,7 +910,7 @@ public class ZipUtil {
|
||||
*/
|
||||
public static byte[] unZlib(InputStream in, int length) {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream(length);
|
||||
inflater(in, out, false);
|
||||
Deflate.of(in, out, false).inflater();
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
@ -1023,123 +945,6 @@ public class ZipUtil {
|
||||
|
||||
// ---------------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 获得 {@link ZipOutputStream}
|
||||
*
|
||||
* @param zipFile 压缩文件
|
||||
* @param charset 编码
|
||||
* @return {@link ZipOutputStream}
|
||||
*/
|
||||
private static ZipOutputStream getZipOutputStream(File zipFile, Charset charset) {
|
||||
return getZipOutputStream(FileUtil.getOutputStream(zipFile), charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得 {@link ZipOutputStream}
|
||||
*
|
||||
* @param out 压缩文件流
|
||||
* @param charset 编码
|
||||
* @return {@link ZipOutputStream}
|
||||
*/
|
||||
private static ZipOutputStream getZipOutputStream(OutputStream out, Charset charset) {
|
||||
if (out instanceof ZipOutputStream) {
|
||||
return (ZipOutputStream) out;
|
||||
}
|
||||
return new ZipOutputStream(out, ObjectUtil.defaultIfNull(charset, DEFAULT_CHARSET));
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归压缩文件夹<br>
|
||||
* srcRootDir决定了路径截取的位置,例如:<br>
|
||||
* file的路径为d:/a/b/c/d.txt,srcRootDir为d:/a/b,则压缩后的文件与目录为结构为c/d.txt
|
||||
*
|
||||
* @param out 压缩文件存储对象
|
||||
* @param srcRootDir 被压缩的文件夹根目录
|
||||
* @param file 当前递归压缩的文件或目录对象
|
||||
* @param filter 文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩)
|
||||
* @throws UtilException IO异常
|
||||
*/
|
||||
private static void zip(File file, String srcRootDir, ZipOutputStream out, FileFilter filter) throws UtilException {
|
||||
if (null == file || (null != filter && false == filter.accept(file))) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String subPath = FileUtil.subPath(srcRootDir, file); // 获取文件相对于压缩文件夹根目录的子路径
|
||||
if (file.isDirectory()) {// 如果是目录,则压缩压缩目录中的文件或子目录
|
||||
final File[] files = file.listFiles();
|
||||
if (ArrayUtil.isEmpty(files)) {
|
||||
// 加入目录,只有空目录时才加入目录,非空时会在创建文件时自动添加父级目录
|
||||
addDir(subPath, out);
|
||||
} else{
|
||||
// 压缩目录下的子文件或目录
|
||||
for (File childFile : files) {
|
||||
zip(childFile, srcRootDir, out, filter);
|
||||
}
|
||||
}
|
||||
} else {// 如果是文件或其它符号,则直接压缩该文件
|
||||
add(file, subPath, out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文件到压缩包
|
||||
*
|
||||
* @param file 需要压缩的文件
|
||||
* @param path 在压缩文件中的路径
|
||||
* @param out 压缩文件存储对象
|
||||
* @throws IORuntimeException IO异常
|
||||
* @since 4.0.5
|
||||
*/
|
||||
private static void add(File file, String path, ZipOutputStream out) throws IORuntimeException {
|
||||
add(FileUtil.getInputStream(file), path, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文件流到压缩包,添加后关闭流
|
||||
*
|
||||
* @param in 需要压缩的输入流,使用完后自动关闭
|
||||
* @param path 压缩的路径
|
||||
* @param out 压缩文件存储对象
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
private static void add(InputStream in, String path, ZipOutputStream out) throws IORuntimeException {
|
||||
if (null == in) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
out.putNextEntry(new ZipEntry(path));
|
||||
IoUtil.copy(in, out);
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
} finally {
|
||||
IoUtil.close(in);
|
||||
closeEntry(out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在压缩包中新建目录
|
||||
*
|
||||
* @param path 压缩的路径
|
||||
* @param out 压缩文件存储对象
|
||||
* @throws UtilException IO异常
|
||||
*/
|
||||
private static void addDir(String path, ZipOutputStream out) throws UtilException {
|
||||
if(StrUtil.isEmpty(path)){
|
||||
// 空路径不处理
|
||||
return;
|
||||
}
|
||||
|
||||
path = StrUtil.addSuffixIfNot(path, StrUtil.SLASH);
|
||||
try {
|
||||
out.putNextEntry(new ZipEntry(path));
|
||||
} catch (IOException e) {
|
||||
throw new UtilException(e);
|
||||
} finally {
|
||||
closeEntry(out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断压缩文件保存的路径是否为源文件路径的子文件夹,如果是,则抛出异常(防止无限递归压缩的发生)
|
||||
*
|
||||
@ -1166,19 +971,6 @@ public class ZipUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭当前Entry,继续下一个Entry
|
||||
*
|
||||
* @param out ZipOutputStream
|
||||
*/
|
||||
private static void closeEntry(ZipOutputStream out) {
|
||||
try {
|
||||
out.closeEntry();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Zip中读取文件流并写出到文件
|
||||
*
|
||||
@ -1190,43 +982,6 @@ public class ZipUtil {
|
||||
private static void write(ZipFile zipFile, ZipEntry zipEntry, File outItemFile) throws IORuntimeException {
|
||||
FileUtil.writeFromStream(getStream(zipFile, zipEntry), outItemFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Zlib流解压到out中
|
||||
*
|
||||
* @param in zlib数据流
|
||||
* @param out 输出
|
||||
* @param nowrap true表示兼容Gzip压缩
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private static void inflater(InputStream in, OutputStream out, boolean nowrap) {
|
||||
final InflaterOutputStream ios = (out instanceof InflaterOutputStream) ? (InflaterOutputStream) out : new InflaterOutputStream(out, new Inflater(nowrap));
|
||||
IoUtil.copy(in, ios);
|
||||
try {
|
||||
ios.finish();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将普通数据流压缩成zlib到out中
|
||||
*
|
||||
* @param in zlib数据流
|
||||
* @param out 输出
|
||||
* @param level 压缩级别,0~9
|
||||
* @param nowrap true表示兼容Gzip压缩
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private static void deflater(InputStream in, OutputStream out, int level, boolean nowrap) {
|
||||
final DeflaterOutputStream ios = (out instanceof DeflaterOutputStream) ? (DeflaterOutputStream) out : new DeflaterOutputStream(out, new Deflater(level, nowrap));
|
||||
IoUtil.copy(in, ios);
|
||||
try {
|
||||
ios.finish();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------------------------------- Private method end
|
||||
|
||||
}
|
||||
|
18
hutool-core/src/test/java/cn/hutool/core/compress/ZipReaderTest.java
Executable file
18
hutool-core/src/test/java/cn/hutool/core/compress/ZipReaderTest.java
Executable file
@ -0,0 +1,18 @@
|
||||
package cn.hutool.core.compress;
|
||||
|
||||
import cn.hutool.core.lang.Console;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ZipReaderTest {
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void unzipTest() {
|
||||
File unzip = ZipUtil.unzip("d:/java.zip", "d:/test/java");
|
||||
Console.log(unzip);
|
||||
}
|
||||
}
|
16
hutool-core/src/test/java/cn/hutool/core/compress/ZipWriterTest.java
Executable file
16
hutool-core/src/test/java/cn/hutool/core/compress/ZipWriterTest.java
Executable file
@ -0,0 +1,16 @@
|
||||
package cn.hutool.core.compress;
|
||||
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ZipWriterTest {
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void zipDirTest() {
|
||||
ZipUtil.zip(new File("d:/test"));
|
||||
}
|
||||
}
|
@ -19,21 +19,21 @@ import java.nio.charset.Charset;
|
||||
*
|
||||
*/
|
||||
public class ZipUtilTest {
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void zipDirTest() {
|
||||
ZipUtil.zip(new File("e:/picTest/picSubTest"));
|
||||
ZipUtil.zip(new File("d:/test"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void unzipTest() {
|
||||
File unzip = ZipUtil.unzip("f:/test/apache-maven-3.6.2.zip", "f:\\test");
|
||||
Console.log(unzip);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void unzipTest2() {
|
||||
@ -47,46 +47,46 @@ public class ZipUtilTest {
|
||||
File unzip = ZipUtil.unzip(FileUtil.getInputStream("e:/test/hutool-core-5.1.0.jar"), FileUtil.file("e:/test/"), CharsetUtil.CHARSET_UTF_8);
|
||||
Console.log(unzip);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void unzipChineseTest() {
|
||||
ZipUtil.unzip("d:/测试.zip");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void unzipFileBytesTest() {
|
||||
byte[] fileBytes = ZipUtil.unzipFileBytes(FileUtil.file("e:/02 电力相关设备及服务2-241-.zip"), CharsetUtil.CHARSET_GBK, "images/CE-EP-HY-MH01-ES-0001.jpg");
|
||||
Assert.assertNotNull(fileBytes);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void gzipTest() {
|
||||
String data = "我是一个需要压缩的很长很长的字符串";
|
||||
byte[] bytes = StrUtil.utf8Bytes(data);
|
||||
byte[] gzip = ZipUtil.gzip(bytes);
|
||||
|
||||
|
||||
//保证gzip长度正常
|
||||
Assert.assertEquals(68, gzip.length);
|
||||
|
||||
|
||||
byte[] unGzip = ZipUtil.unGzip(gzip);
|
||||
//保证正常还原
|
||||
Assert.assertEquals(data, StrUtil.utf8Str(unGzip));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void zlibTest() {
|
||||
String data = "我是一个需要压缩的很长很长的字符串";
|
||||
byte[] bytes = StrUtil.utf8Bytes(data);
|
||||
byte[] gzip = ZipUtil.zlib(bytes, 0);
|
||||
|
||||
|
||||
//保证zlib长度正常
|
||||
Assert.assertEquals(62, gzip.length);
|
||||
byte[] unGzip = ZipUtil.unZlib(gzip);
|
||||
//保证正常还原
|
||||
Assert.assertEquals(data, StrUtil.utf8Str(unGzip));
|
||||
|
||||
|
||||
gzip = ZipUtil.zlib(bytes, 9);
|
||||
//保证zlib长度正常
|
||||
Assert.assertEquals(56, gzip.length);
|
||||
|
Loading…
x
Reference in New Issue
Block a user