118 lines
3.0 KiB
Java
118 lines
3.0 KiB
Java
package com.imyeyu.compress;
|
|
|
|
import com.imyeyu.io.IO;
|
|
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
|
|
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
|
|
|
|
import java.io.File;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
|
|
/**
|
|
* 7z 解压器
|
|
*
|
|
* @author 夜雨
|
|
* @version 2024-06-30 19:42
|
|
*/
|
|
public class Z7Decompressor extends Decompressor {
|
|
|
|
@Override
|
|
public void run(File fromFile, String toPath) throws Exception {
|
|
initByteProgress(readTotalSize(fromFile));
|
|
try {
|
|
super.run(fromFile, toPath);
|
|
} finally {
|
|
resetProgress();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void run(InputStream fromStream, String toPath) throws Exception {
|
|
Path tempFile = writeTempFile(fromStream);
|
|
try (SevenZFile file = SevenZFile.builder().setFile(tempFile.toFile()).get()) {
|
|
SevenZArchiveEntry entry;
|
|
boolean processed = false;
|
|
while ((entry = file.getNextEntry()) != null) {
|
|
if (entry.isDirectory()) {
|
|
IO.dir(IO.fitPath(toPath) + entry.getName());
|
|
} else {
|
|
File toFile = IO.file(IO.fitPath(toPath) + entry.getName());
|
|
try (OutputStream outputStream = IO.getOutputStream(toFile)) {
|
|
copySevenZEntry(file, entry, outputStream);
|
|
outputStream.flush();
|
|
}
|
|
handleFile(toFile);
|
|
processed = true;
|
|
}
|
|
}
|
|
if (processed) {
|
|
finishProgress();
|
|
}
|
|
} finally {
|
|
Files.deleteIfExists(tempFile);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 将输入流写入临时文件
|
|
*
|
|
* @param fromStream 输入流
|
|
* @return 临时文件路径
|
|
* @throws Exception 写入失败
|
|
*/
|
|
private Path writeTempFile(InputStream fromStream) throws Exception {
|
|
Path tempFile = Files.createTempFile("timi-compress-", ".7z");
|
|
try (OutputStream outputStream = Files.newOutputStream(tempFile)) {
|
|
transfer(fromStream, outputStream, false);
|
|
outputStream.flush();
|
|
}
|
|
return tempFile;
|
|
}
|
|
|
|
/**
|
|
* 复制当前 7z 条目数据
|
|
*
|
|
* @param file 7z 文件
|
|
* @param entry 当前条目
|
|
* @param toStream 输出流
|
|
* @throws Exception 复制失败
|
|
*/
|
|
private void copySevenZEntry(SevenZFile file, SevenZArchiveEntry entry, OutputStream toStream) throws Exception {
|
|
byte[] buffer = new byte[8192];
|
|
long remain = entry.getSize();
|
|
while (0 < remain) {
|
|
awaitIfPaused();
|
|
ensureRunning();
|
|
int length = file.read(buffer, 0, (int) Math.min(buffer.length, remain));
|
|
if (length < 0) {
|
|
break;
|
|
}
|
|
toStream.write(buffer, 0, length);
|
|
remain -= length;
|
|
handleTransferred(length);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 读取压缩包解压总字节数
|
|
*
|
|
* @param fromFile 压缩文件
|
|
* @return 总字节数
|
|
* @throws Exception 读取失败
|
|
*/
|
|
private long readTotalSize(File fromFile) throws Exception {
|
|
long totalSize = 0L;
|
|
try (SevenZFile file = SevenZFile.builder().setFile(fromFile).get()) {
|
|
SevenZArchiveEntry entry;
|
|
while ((entry = file.getNextEntry()) != null) {
|
|
if (!entry.isDirectory()) {
|
|
totalSize += entry.getSize();
|
|
}
|
|
}
|
|
}
|
|
return totalSize;
|
|
}
|
|
}
|