package com.imyeyu.compress; import com.imyeyu.io.IO; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import java.io.File; import java.io.InputStream; import java.io.OutputStream; /** * Gzip 解压器 * * @author 夜雨 * @version 2024-06-30 19:47 */ public class GZipDecompressor extends Decompressor { /** * 创建解压器 * * @param fromFile 源压缩文件 * @return 解压器 */ public static GZipDecompressor from(File fromFile) { return new GZipDecompressor().of(fromFile); } /** * 创建解压器 * * @param fromPath 源压缩文件路径 * @return 解压器 */ public static GZipDecompressor from(String fromPath) { return new GZipDecompressor().of(fromPath); } /** * 创建解压器 * * @param fromStream 源压缩输入流 * @return 解压器 */ public static GZipDecompressor from(InputStream fromStream) { return new GZipDecompressor().of(fromStream); } @Override protected void toPath(File fromFile, String toPath) throws Exception { initByteProgress(readTotalSize(fromFile)); try { super.toPath(fromFile, toPath); } finally { resetProgress(); } } @Override protected void toPath(InputStream fromStream, String toPath) throws Exception { try ( GzipCompressorInputStream gzipInputStream = new GzipCompressorInputStream(nonClosing(fromStream)); TarArchiveInputStream tarInputStream = new TarArchiveInputStream(gzipInputStream) ) { TarArchiveEntry entry; boolean processed = false; while ((entry = tarInputStream.getNextEntry()) != null) { String path = IO.fitPath(toPath) + entry.getName(); if (entry.isDirectory()) { IO.dir(path); } else { File toFile = IO.file(path); try (OutputStream outputStream = IO.getOutputStream(toFile)) { transfer(tarInputStream, outputStream); outputStream.flush(); } handleFile(toFile); processed = true; } } if (processed) { finishProgress(); } } } /** * 读取压缩包解压总字节数 * * @param fromFile 压缩文件 * @return 总字节数 * @throws Exception 读取失败 */ private long readTotalSize(File fromFile) throws Exception { long totalSize = 0L; try ( InputStream inputStream = IO.getInputStream(fromFile); GzipCompressorInputStream gzipInputStream = new GzipCompressorInputStream(inputStream); TarArchiveInputStream tarInputStream = new TarArchiveInputStream(gzipInputStream) ) { TarArchiveEntry entry; while ((entry = tarInputStream.getNextEntry()) != null) { if (!entry.isDirectory()) { totalSize += entry.getSize(); } } } return totalSize; } }