package com.imyeyu.compress; import com.imyeyu.io.IO; import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry; import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; /** * 7z 压缩器 * * @author 夜雨 * @version 2024-06-30 19:40 */ public class Z7Compressor extends Compressor { /** * 创建压缩器 * * @param fromPath 源路径 * @return 压缩器 */ public static Z7Compressor of(String fromPath) { return new Z7Compressor().from(fromPath); } /** * 创建压缩器 * * @param fromFile 源文件 * @return 压缩器 */ public static Z7Compressor of(File fromFile) { return new Z7Compressor().from(fromFile); } @Override protected void toStream(String fromPath, OutputStream toStream) throws Exception { Path tempFile = Files.createTempFile("timi-compress-", ".7z"); try { from(fromPath).toFile(tempFile.toFile()); try (InputStream inputStream = Files.newInputStream(tempFile)) { transfer(inputStream, toStream, false); toStream.flush(); } } finally { Files.deleteIfExists(tempFile); } } @Override protected void toFile(String fromPath, File toFile) throws Exception { File fromFile = new File(fromPath); List files = IO.listFile(fromFile); String basePath = files.getFirst().getParentFile().getAbsolutePath(); initByteProgress(IO.calcSize(fromFile)); try (SevenZOutputFile outputFile = new SevenZOutputFile(toFile)) { for (File sourceFile : files) { String name = sourceFile.getAbsolutePath().substring(basePath.length() + 1); SevenZArchiveEntry entry = outputFile.createArchiveEntry(sourceFile, normalizeEntryName(name)); outputFile.putArchiveEntry(entry); writeSevenZEntry(outputFile, sourceFile); outputFile.closeArchiveEntry(); handleFile(sourceFile); } outputFile.finish(); finishProgress(); } catch (Exception exception) { if (isInterrupt) { IO.destroy(toFile); } throw exception; } finally { resetProgress(); } if (isInterrupt) { IO.destroy(toFile); } } /** * 写入 7z 条目内容 * * @param outputFile 7z 输出文件 * @param sourceFile 源文件 * @throws Exception 写入失败 */ private void writeSevenZEntry(SevenZOutputFile outputFile, File sourceFile) throws Exception { byte[] buffer = new byte[8192]; try (InputStream inputStream = IO.getInputStream(sourceFile)) { int length; while ((length = inputStream.read(buffer)) != -1) { awaitIfPaused(); ensureRunning(); outputFile.write(buffer, 0, length); handleTransferred(length); } } } }