All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hutool.core.util.ZipUtil Maven / Gradle / Ivy

Go to download

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

There is a newer version: 5.8.34
Show newest version
package cn.hutool.core.util;

import cn.hutool.core.collection.EnumerationIter;
import cn.hutool.core.compress.Deflate;
import cn.hutool.core.compress.Gzip;
import cn.hutool.core.compress.ZipCopyVisitor;
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;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.LimitedInputStream;
import cn.hutool.core.io.file.FileSystemUtil;
import cn.hutool.core.io.file.PathUtil;
import cn.hutool.core.io.resource.Resource;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
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.nio.file.CopyOption;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.function.Consumer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * 压缩工具类
 *
 * @author Looly
 * @see cn.hutool.core.compress.ZipWriter
 */
public class ZipUtil {

	private static final int DEFAULT_BYTE_ARRAY_LENGTH = 32;

	/**
	 * 默认编码,使用平台相关编码
	 */
	private static final Charset DEFAULT_CHARSET = CharsetUtil.defaultCharset();

	/**
	 * 将Zip文件转换为{@link ZipFile}
	 *
	 * @param file    zip文件
	 * @param charset 解析zip文件的编码,null表示{@link CharsetUtil#CHARSET_UTF_8}
	 * @return {@link ZipFile}
	 */
	public static ZipFile toZipFile(File file, Charset charset) {
		try {
			return new ZipFile(file, ObjectUtil.defaultIfNull(charset, CharsetUtil.CHARSET_UTF_8));
		} catch (IOException e) {
			throw new IORuntimeException(e);
		}
	}

	/**
	 * 获取指定{@link ZipEntry}的流,用于读取这个entry的内容
* 此处使用{@link LimitedInputStream} 限制最大写出大小,避免ZIP bomb漏洞 * * @param zipFile {@link ZipFile} * @param zipEntry {@link ZipEntry} * @return 流 * @since 5.5.2 */ public static InputStream getStream(ZipFile zipFile, ZipEntry zipEntry) { try { return new LimitedInputStream(zipFile.getInputStream(zipEntry), zipEntry.getSize()); } catch (IOException e) { throw new IORuntimeException(e); } } /** * 获得 {@link ZipOutputStream} * * @param out 压缩文件流 * @param charset 编码 * @return {@link ZipOutputStream} * @since 5.8.0 */ public static ZipOutputStream getZipOutputStream(OutputStream out, Charset charset) { if (out instanceof ZipOutputStream) { return (ZipOutputStream) out; } return new ZipOutputStream(out, charset); } /** * 在zip文件中添加新文件或目录
* 新文件添加在zip根目录,文件夹包括其本身和内容
* 如果待添加文件夹是系统根路径(如/或c:/),则只复制文件夹下的内容 * * @param zipPath zip文件的Path * @param appendFilePath 待添加文件Path(可以是文件夹) * @param options 拷贝选项,可选是否覆盖等 * @throws IORuntimeException IO异常 * @since 5.7.15 */ public static void append(Path zipPath, Path appendFilePath, CopyOption... options) throws IORuntimeException { try (FileSystem zipFileSystem = FileSystemUtil.createZip(zipPath.toString())) { if (Files.isDirectory(appendFilePath)) { Path source = appendFilePath.getParent(); if (null == source) { // 如果用户提供的是根路径,则不复制目录,直接复制目录下的内容 source = appendFilePath; } Files.walkFileTree(appendFilePath, new ZipCopyVisitor(source, zipFileSystem, options)); } else { Files.copy(appendFilePath, zipFileSystem.getPath(PathUtil.getName(appendFilePath)), options); } } catch (FileAlreadyExistsException ignored) { // 不覆盖情况下,文件已存在, 跳过 } catch (IOException e) { throw new IORuntimeException(e); } } /** * 打包到当前目录,使用默认编码UTF-8 * * @param srcPath 源文件路径 * @return 打包好的压缩文件 * @throws UtilException IO异常 */ public static File zip(String srcPath) throws UtilException { return zip(srcPath, DEFAULT_CHARSET); } /** * 打包到当前目录 * * @param srcPath 源文件路径 * @param charset 编码 * @return 打包好的压缩文件 * @throws UtilException IO异常 */ public static File zip(String srcPath, Charset charset) throws UtilException { return zip(FileUtil.file(srcPath), charset); } /** * 打包到当前目录,使用默认编码UTF-8 * * @param srcFile 源文件或目录 * @return 打包好的压缩文件 * @throws UtilException IO异常 */ public static File zip(File srcFile) throws UtilException { return zip(srcFile, DEFAULT_CHARSET); } /** * 打包到当前目录 * * @param srcFile 源文件或目录 * @param charset 编码 * @return 打包好的压缩文件 * @throws UtilException IO异常 */ public static File zip(File srcFile, Charset charset) throws UtilException { final File zipFile = FileUtil.file(srcFile.getParentFile(), FileUtil.mainName(srcFile) + ".zip"); zip(zipFile, charset, false, srcFile); return zipFile; } /** * 对文件或文件目录进行压缩
* 不包含被打包目录 * * @param srcPath 要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径 * @param zipPath 压缩文件保存的路径,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @return 压缩好的Zip文件 * @throws UtilException IO异常 */ public static File zip(String srcPath, String zipPath) throws UtilException { return zip(srcPath, zipPath, false); } /** * 对文件或文件目录进行压缩
* * @param srcPath 要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径 * @param zipPath 压缩文件保存的路径,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param withSrcDir 是否包含被打包目录 * @return 压缩文件 * @throws UtilException IO异常 */ public static File zip(String srcPath, String zipPath, boolean withSrcDir) throws UtilException { return zip(srcPath, zipPath, DEFAULT_CHARSET, withSrcDir); } /** * 对文件或文件目录进行压缩
* * @param srcPath 要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径 * @param zipPath 压缩文件保存的路径,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param charset 编码 * @param withSrcDir 是否包含被打包目录 * @return 压缩文件 * @throws UtilException IO异常 */ public static File zip(String srcPath, String zipPath, Charset charset, boolean withSrcDir) throws UtilException { final File srcFile = FileUtil.file(srcPath); final File zipFile = FileUtil.file(zipPath); zip(zipFile, charset, withSrcDir, srcFile); return zipFile; } /** * 对文件或文件目录进行压缩
* 使用默认UTF-8编码 * * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩 * @param srcFiles 要压缩的源文件或目录。 * @return 压缩文件 * @throws UtilException IO异常 */ public static File zip(File zipFile, boolean withSrcDir, File... srcFiles) throws UtilException { return zip(zipFile, DEFAULT_CHARSET, withSrcDir, srcFiles); } /** * 对文件或文件目录进行压缩 * * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param charset 编码 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩 * @param srcFiles 要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径 * @return 压缩文件 * @throws UtilException IO异常 */ public static File zip(File zipFile, Charset charset, boolean withSrcDir, File... srcFiles) throws UtilException { return zip(zipFile, charset, withSrcDir, null, srcFiles); } /** * 对文件或文件目录进行压缩 * * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param charset 编码 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩 * @param filter 文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩) * @param srcFiles 要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径 * @return 压缩文件 * @throws IORuntimeException IO异常 * @since 4.6.5 */ public static File zip(File zipFile, Charset charset, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException { validateFiles(zipFile, srcFiles); //noinspection resource ZipWriter.of(zipFile, charset).add(withSrcDir, filter, srcFiles).close(); return zipFile; } /** * 对文件或文件目录进行压缩 * * @param out 生成的Zip到的目标流,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param charset 编码 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩 * @param filter 文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩) * @param srcFiles 要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径 * @throws IORuntimeException IO异常 * @since 5.1.1 */ public static void zip(OutputStream out, Charset charset, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException { ZipWriter.of(out, charset).add(withSrcDir, filter, srcFiles).close(); } /** * 对文件或文件目录进行压缩 * * @param zipOutputStream 生成的Zip到的目标流,自动关闭此流 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩 * @param filter 文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩) * @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 { try (final ZipWriter zipWriter = new ZipWriter(zipOutputStream)) { zipWriter.add(withSrcDir, filter, srcFiles); } } /** * 对流中的数据加入到压缩文件,使用默认UTF-8编码 * * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param path 流数据在压缩文件中的路径或文件名 * @param data 要压缩的数据 * @return 压缩文件 * @throws UtilException IO异常 * @since 3.0.6 */ public static File zip(File zipFile, String path, String data) throws UtilException { return zip(zipFile, path, data, DEFAULT_CHARSET); } /** * 对流中的数据加入到压缩文件
* * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param path 流数据在压缩文件中的路径或文件名 * @param data 要压缩的数据 * @param charset 编码 * @return 压缩文件 * @throws UtilException IO异常 * @since 3.2.2 */ public static File zip(File zipFile, String path, String data, Charset charset) throws UtilException { return zip(zipFile, path, IoUtil.toStream(data, charset), charset); } /** * 对流中的数据加入到压缩文件
* 使用默认编码UTF-8 * * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param path 流数据在压缩文件中的路径或文件名 * @param in 要压缩的源 * @return 压缩文件 * @throws UtilException IO异常 * @since 3.0.6 */ public static File zip(File zipFile, String path, InputStream in) throws UtilException { return zip(zipFile, path, in, DEFAULT_CHARSET); } /** * 对流中的数据加入到压缩文件 * * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param path 流数据在压缩文件中的路径或文件名 * @param in 要压缩的源,默认关闭 * @param charset 编码 * @return 压缩文件 * @throws UtilException IO异常 * @since 3.2.2 */ public static File zip(File zipFile, String path, InputStream in, Charset charset) throws UtilException { return zip(zipFile, new String[]{path}, new InputStream[]{in}, charset); } /** * 对流中的数据加入到压缩文件
* 路径列表和流列表长度必须一致 * * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param paths 流数据在压缩文件中的路径或文件名 * @param ins 要压缩的源,添加完成后自动关闭流 * @return 压缩文件 * @throws UtilException IO异常 * @since 3.0.9 */ public static File zip(File zipFile, String[] paths, InputStream[] ins) throws UtilException { return zip(zipFile, paths, ins, DEFAULT_CHARSET); } /** * 对流中的数据加入到压缩文件
* 路径列表和流列表长度必须一致 * * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param paths 流数据在压缩文件中的路径或文件名 * @param ins 要压缩的源,添加完成后自动关闭流 * @param charset 编码 * @return 压缩文件 * @throws UtilException IO异常 * @since 3.0.9 */ public static File zip(File zipFile, String[] paths, InputStream[] ins, Charset charset) throws UtilException { try (final ZipWriter zipWriter = ZipWriter.of(zipFile, charset)) { zipWriter.add(paths, ins); } return zipFile; } /** * 将文件流压缩到目标流中 * * @param out 目标流,压缩完成自动关闭 * @param paths 流数据在压缩文件中的路径或文件名 * @param ins 要压缩的源,添加完成后自动关闭流 * @since 5.5.2 */ public static void zip(OutputStream out, String[] paths, InputStream[] ins) { zip(getZipOutputStream(out, DEFAULT_CHARSET), paths, ins); } /** * 将文件流压缩到目标流中 * * @param zipOutputStream 目标流,压缩完成自动关闭 * @param paths 流数据在压缩文件中的路径或文件名 * @param ins 要压缩的源,添加完成后自动关闭流 * @throws IORuntimeException IO异常 * @since 5.5.2 */ public static void zip(ZipOutputStream zipOutputStream, String[] paths, InputStream[] ins) throws IORuntimeException { try (final ZipWriter zipWriter = new ZipWriter(zipOutputStream)) { zipWriter.add(paths, ins); } } /** * 对流中的数据加入到压缩文件
* 路径列表和流列表长度必须一致 * * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹 * @param charset 编码 * @param resources 需要压缩的资源,资源的路径为{@link Resource#getName()} * @return 压缩文件 * @throws UtilException IO异常 * @since 5.5.2 */ public static File zip(File zipFile, Charset charset, Resource... resources) throws UtilException { //noinspection resource ZipWriter.of(zipFile, charset).add(resources).close(); return zipFile; } // ---------------------------------------------------------------------------------------------- Unzip /** * 解压到文件名相同的目录中,默认编码UTF-8 * * @param zipFilePath 压缩文件路径 * @return 解压的目录 * @throws UtilException IO异常 */ public static File unzip(String zipFilePath) throws UtilException { return unzip(zipFilePath, DEFAULT_CHARSET); } /** * 解压到文件名相同的目录中 * * @param zipFilePath 压缩文件路径 * @param charset 编码 * @return 解压的目录 * @throws UtilException IO异常 * @since 3.2.2 */ public static File unzip(String zipFilePath, Charset charset) throws UtilException { return unzip(FileUtil.file(zipFilePath), charset); } /** * 解压到文件名相同的目录中,使用UTF-8编码 * * @param zipFile 压缩文件 * @return 解压的目录 * @throws UtilException IO异常 * @since 3.2.2 */ public static File unzip(File zipFile) throws UtilException { return unzip(zipFile, DEFAULT_CHARSET); } /** * 解压到文件名相同的目录中 * * @param zipFile 压缩文件 * @param charset 编码 * @return 解压的目录 * @throws UtilException IO异常 * @since 3.2.2 */ public static File unzip(File zipFile, Charset charset) throws UtilException { final File destDir = FileUtil.file(zipFile.getParentFile(), FileUtil.mainName(zipFile)); return unzip(zipFile, destDir, charset); } /** * 解压,默认UTF-8编码 * * @param zipFilePath 压缩文件的路径 * @param outFileDir 解压到的目录 * @return 解压的目录 * @throws UtilException IO异常 */ public static File unzip(String zipFilePath, String outFileDir) throws UtilException { return unzip(zipFilePath, outFileDir, DEFAULT_CHARSET); } /** * 解压 * * @param zipFilePath 压缩文件的路径 * @param outFileDir 解压到的目录 * @param charset 编码 * @return 解压的目录 * @throws UtilException IO异常 */ public static File unzip(String zipFilePath, String outFileDir, Charset charset) throws UtilException { return unzip(FileUtil.file(zipFilePath), FileUtil.mkdir(outFileDir), charset); } /** * 解压,默认使用UTF-8编码 * * @param zipFile zip文件 * @param outFile 解压到的目录 * @return 解压的目录 * @throws UtilException IO异常 */ public static File unzip(File zipFile, File outFile) throws UtilException { return unzip(zipFile, outFile, DEFAULT_CHARSET); } /** * 解压 * * @param zipFile zip文件 * @param outFile 解压到的目录 * @param charset 编码 * @return 解压的目录 * @since 3.2.2 */ public static File unzip(File zipFile, File outFile, Charset charset) { return unzip(toZipFile(zipFile, charset), outFile); } /** * 解压 * * @param zipFile zip文件,附带编码信息,使用完毕自动关闭 * @param outFile 解压到的目录 * @return 解压的目录 * @throws IORuntimeException IO异常 * @since 4.5.8 */ public static File unzip(ZipFile zipFile, File outFile) throws IORuntimeException { return unzip(zipFile, outFile, -1); } /** * 限制解压后文件大小 * * @param zipFile zip文件,附带编码信息,使用完毕自动关闭 * @param outFile 解压到的目录 * @param limit 限制解压文件大小(单位B) * @return 解压的目录 * @throws IORuntimeException IO异常 * @since 5.8.5 */ public static File unzip(ZipFile zipFile, File outFile, long limit) throws IORuntimeException { if (outFile.exists() && outFile.isFile()) { throw new IllegalArgumentException( StrUtil.format("Target path [{}] exist!", outFile.getAbsolutePath())); } // pr#726@Gitee if (limit > 0) { final Enumeration zipEntries = zipFile.entries(); long zipFileSize = 0L; while (zipEntries.hasMoreElements()) { final ZipEntry zipEntry = zipEntries.nextElement(); zipFileSize += zipEntry.getSize(); if (zipFileSize > limit) { throw new IllegalArgumentException("The file size exceeds the limit"); } } } try (final ZipReader reader = new ZipReader(zipFile)) { reader.readTo(outFile); } return outFile; } /** * 获取压缩包中的指定文件流 * * @param zipFile 压缩文件 * @param charset 编码 * @param path 需要提取文件的文件名或路径 * @return 压缩文件流,如果未找到返回{@code null} * @since 5.5.2 */ public static InputStream get(File zipFile, Charset charset, String path) { return get(toZipFile(zipFile, charset), path); } /** * 获取压缩包中的指定文件流 * * @param zipFile 压缩文件 * @param path 需要提取文件的文件名或路径 * @return 压缩文件流,如果未找到返回{@code null} * @since 5.5.2 */ public static InputStream get(ZipFile zipFile, String path) { final ZipEntry entry = zipFile.getEntry(path); if (null != entry) { return getStream(zipFile, entry); } return null; } /** * 读取并处理Zip文件中的每一个{@link ZipEntry} * * @param zipFile Zip文件 * @param consumer {@link ZipEntry}处理器 * @since 5.5.2 */ public static void read(ZipFile zipFile, Consumer consumer) { try (final ZipReader reader = new ZipReader(zipFile)) { reader.read(consumer); } } /** * 解压
* ZIP条目不使用高速缓冲。 * * @param in zip文件流,使用完毕自动关闭 * @param outFile 解压到的目录 * @param charset 编码 * @return 解压的目录 * @throws UtilException IO异常 * @since 4.5.8 */ public static File unzip(InputStream in, File outFile, Charset charset) throws UtilException { if (null == charset) { charset = DEFAULT_CHARSET; } return unzip(new ZipInputStream(in, charset), outFile); } /** * 解压
* ZIP条目不使用高速缓冲。 * * @param zipStream zip文件流,包含编码信息 * @param outFile 解压到的目录 * @return 解压的目录 * @throws UtilException IO异常 * @since 4.5.8 */ public static File unzip(ZipInputStream zipStream, File outFile) throws UtilException { try (final ZipReader reader = new ZipReader(zipStream)) { reader.readTo(outFile); } return outFile; } /** * 读取并处理Zip流中的每一个{@link ZipEntry} * * @param zipStream zip文件流,包含编码信息 * @param consumer {@link ZipEntry}处理器 * @since 5.5.2 */ public static void read(ZipInputStream zipStream, Consumer consumer) { try (final ZipReader reader = new ZipReader(zipStream)) { reader.read(consumer); } } /** * 从Zip文件中提取指定的文件为bytes * * @param zipFilePath Zip文件 * @param name 文件名,如果存在于子文件夹中,此文件名必须包含目录名,例如images/aaa.txt * @return 文件内容bytes * @since 4.1.8 */ public static byte[] unzipFileBytes(String zipFilePath, String name) { return unzipFileBytes(zipFilePath, DEFAULT_CHARSET, name); } /** * 从Zip文件中提取指定的文件为bytes * * @param zipFilePath Zip文件 * @param charset 编码 * @param name 文件名,如果存在于子文件夹中,此文件名必须包含目录名,例如images/aaa.txt * @return 文件内容bytes * @since 4.1.8 */ public static byte[] unzipFileBytes(String zipFilePath, Charset charset, String name) { return unzipFileBytes(FileUtil.file(zipFilePath), charset, name); } /** * 从Zip文件中提取指定的文件为bytes * * @param zipFile Zip文件 * @param name 文件名,如果存在于子文件夹中,此文件名必须包含目录名,例如images/aaa.txt * @return 文件内容bytes * @since 4.1.8 */ public static byte[] unzipFileBytes(File zipFile, String name) { return unzipFileBytes(zipFile, DEFAULT_CHARSET, name); } /** * 从Zip文件中提取指定的文件为bytes * * @param zipFile Zip文件 * @param charset 编码 * @param name 文件名,如果存在于子文件夹中,此文件名必须包含目录名,例如images/aaa.txt * @return 文件内容bytes * @since 4.1.8 */ public static byte[] unzipFileBytes(File zipFile, Charset charset, String name) { try (final ZipReader reader = ZipReader.of(zipFile, charset)) { return IoUtil.readBytes(reader.get(name)); } } // ----------------------------------------------------------------------------- Gzip /** * Gzip压缩处理 * * @param content 被压缩的字符串 * @param charset 编码 * @return 压缩后的字节流 * @throws UtilException IO异常 */ public static byte[] gzip(String content, String charset) throws UtilException { return gzip(StrUtil.bytes(content, charset)); } /** * Gzip压缩处理 * * @param buf 被压缩的字节流 * @return 压缩后的字节流 * @throws UtilException IO异常 */ public static byte[] gzip(byte[] buf) throws UtilException { return gzip(new ByteArrayInputStream(buf), buf.length); } /** * Gzip压缩文件 * * @param file 被压缩的文件 * @return 压缩后的字节流 * @throws UtilException IO异常 */ public static byte[] gzip(File file) throws UtilException { BufferedInputStream in = null; try { in = FileUtil.getInputStream(file); return gzip(in, (int) file.length()); } finally { IoUtil.close(in); } } /** * Gzip压缩文件 * * @param in 被压缩的流 * @return 压缩后的字节流 * @throws UtilException IO异常 * @since 4.1.18 */ public static byte[] gzip(InputStream in) throws UtilException { return gzip(in, DEFAULT_BYTE_ARRAY_LENGTH); } /** * Gzip压缩文件 * * @param in 被压缩的流 * @param length 预估长度 * @return 压缩后的字节流 * @throws UtilException IO异常 * @since 4.1.18 */ public static byte[] gzip(InputStream in, int length) throws UtilException { final ByteArrayOutputStream bos = new ByteArrayOutputStream(length); Gzip.of(in, bos).gzip().close(); return bos.toByteArray(); } /** * Gzip解压缩处理 * * @param buf 压缩过的字节流 * @param charset 编码 * @return 解压后的字符串 * @throws UtilException IO异常 */ public static String unGzip(byte[] buf, String charset) throws UtilException { return StrUtil.str(unGzip(buf), charset); } /** * Gzip解压处理 * * @param buf buf * @return bytes * @throws UtilException IO异常 */ public static byte[] unGzip(byte[] buf) throws UtilException { return unGzip(new ByteArrayInputStream(buf), buf.length); } /** * Gzip解压处理 * * @param in Gzip数据 * @return 解压后的数据 * @throws UtilException IO异常 */ public static byte[] unGzip(InputStream in) throws UtilException { return unGzip(in, DEFAULT_BYTE_ARRAY_LENGTH); } /** * Gzip解压处理 * * @param in Gzip数据 * @param length 估算长度,如果无法确定请传入{@link #DEFAULT_BYTE_ARRAY_LENGTH} * @return 解压后的数据 * @throws UtilException IO异常 * @since 4.1.18 */ public static byte[] unGzip(InputStream in, int length) throws UtilException { FastByteArrayOutputStream bos = new FastByteArrayOutputStream(length); Gzip.of(in, bos).unGzip().close(); return bos.toByteArray(); } // ----------------------------------------------------------------------------- Zlib /** * Zlib压缩处理 * * @param content 被压缩的字符串 * @param charset 编码 * @param level 压缩级别,1~9 * @return 压缩后的字节流 * @since 4.1.4 */ public static byte[] zlib(String content, String charset, int level) { return zlib(StrUtil.bytes(content, charset), level); } /** * Zlib压缩文件 * * @param file 被压缩的文件 * @param level 压缩级别 * @return 压缩后的字节流 * @since 4.1.4 */ public static byte[] zlib(File file, int level) { BufferedInputStream in = null; try { in = FileUtil.getInputStream(file); return zlib(in, level, (int) file.length()); } finally { IoUtil.close(in); } } /** * 打成Zlib压缩包 * * @param buf 数据 * @param level 压缩级别,0~9 * @return 压缩后的bytes * @since 4.1.4 */ public static byte[] zlib(byte[] buf, int level) { return zlib(new ByteArrayInputStream(buf), level, buf.length); } /** * 打成Zlib压缩包 * * @param in 数据流 * @param level 压缩级别,0~9 * @return 压缩后的bytes * @since 4.1.19 */ public static byte[] zlib(InputStream in, int level) { return zlib(in, level, DEFAULT_BYTE_ARRAY_LENGTH); } /** * 打成Zlib压缩包 * * @param in 数据流 * @param level 压缩级别,0~9 * @param length 预估大小 * @return 压缩后的bytes * @since 4.1.19 */ public static byte[] zlib(InputStream in, int level, int length) { final ByteArrayOutputStream out = new ByteArrayOutputStream(length); Deflate.of(in, out, false).deflater(level); return out.toByteArray(); } /** * Zlib解压缩处理 * * @param buf 压缩过的字节流 * @param charset 编码 * @return 解压后的字符串 * @since 4.1.4 */ public static String unZlib(byte[] buf, String charset) { return StrUtil.str(unZlib(buf), charset); } /** * 解压缩zlib * * @param buf 数据 * @return 解压后的bytes * @since 4.1.4 */ public static byte[] unZlib(byte[] buf) { return unZlib(new ByteArrayInputStream(buf), buf.length); } /** * 解压缩zlib * * @param in 数据流 * @return 解压后的bytes * @since 4.1.19 */ public static byte[] unZlib(InputStream in) { return unZlib(in, DEFAULT_BYTE_ARRAY_LENGTH); } /** * 解压缩zlib * * @param in 数据流 * @param length 预估长度 * @return 解压后的bytes * @since 4.1.19 */ public static byte[] unZlib(InputStream in, int length) { final ByteArrayOutputStream out = new ByteArrayOutputStream(length); Deflate.of(in, out, false).inflater(); return out.toByteArray(); } /** * 获取Zip文件中指定目录下的所有文件,只显示文件,不显示目录
* 此方法并不会关闭{@link ZipFile}。 * * @param zipFile Zip文件 * @param dir 目录前缀(目录前缀不包含开头的/) * @return 文件列表 * @since 4.6.6 */ public static List listFileNames(ZipFile zipFile, String dir) { if (StrUtil.isNotBlank(dir)) { // 目录尾部添加"/" dir = StrUtil.addSuffixIfNot(dir, StrUtil.SLASH); } final List fileNames = new ArrayList<>(); String name; for (ZipEntry entry : new EnumerationIter<>(zipFile.entries())) { name = entry.getName(); if (StrUtil.isEmpty(dir) || name.startsWith(dir)) { final String nameSuffix = StrUtil.removePrefix(name, dir); if (StrUtil.isNotEmpty(nameSuffix) && false == StrUtil.contains(nameSuffix, CharUtil.SLASH)) { fileNames.add(nameSuffix); } } } return fileNames; } // ---------------------------------------------------------------------------------------------- Private method start /** * 判断压缩文件保存的路径是否为源文件路径的子文件夹,如果是,则抛出异常(防止无限递归压缩的发生) * * @param zipFile 压缩后的产生的文件路径 * @param srcFiles 被压缩的文件或目录 */ private static void validateFiles(File zipFile, File... srcFiles) throws UtilException { if (zipFile.isDirectory()) { throw new UtilException("Zip file [{}] must not be a directory !", zipFile.getAbsoluteFile()); } for (File srcFile : srcFiles) { if (null == srcFile) { continue; } if (false == srcFile.exists()) { throw new UtilException(StrUtil.format("File [{}] not exist!", srcFile.getAbsolutePath())); } // issue#1961@Github // 当 zipFile = new File("temp.zip") 时, zipFile.getParentFile() == null File parentFile; try { parentFile = zipFile.getCanonicalFile().getParentFile(); } catch (IOException e) { parentFile = zipFile.getParentFile(); } // 压缩文件不能位于被压缩的目录内 if (srcFile.isDirectory() && FileUtil.isSub(srcFile, parentFile)) { throw new UtilException("Zip file path [{}] must not be the child directory of [{}] !", zipFile.getPath(), srcFile.getPath()); } } } // ---------------------------------------------------------------------------------------------- Private method end }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy