This commit is contained in:
@@ -1,66 +0,0 @@
|
||||
package com.imyeyu.compress;
|
||||
|
||||
import com.imyeyu.java.bean.CallbackArg;
|
||||
import com.imyeyu.utils.OS;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 抽象解压缩执行器
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2024-06-30 18:09
|
||||
*/
|
||||
public abstract class AbstractCompressor implements OS.FileSystem {
|
||||
|
||||
/** 操作文件回调 */
|
||||
protected CallbackArg<File> fileCallback;
|
||||
|
||||
/** 进度回调 */
|
||||
protected CallbackArg<Double> progressCallback;
|
||||
|
||||
/** 中止 */
|
||||
protected boolean isInterrupt = false;
|
||||
|
||||
/** 暂停 */
|
||||
protected boolean isPause = false;
|
||||
|
||||
/** 暂停锁 */
|
||||
protected final Object pauseLock = new Object();
|
||||
|
||||
/** 暂停 */
|
||||
public void pause() {
|
||||
isPause = true;
|
||||
}
|
||||
|
||||
/** 开始 */
|
||||
public void start() {
|
||||
isPause = false;
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/** 中止 */
|
||||
public void interrupt() {
|
||||
isInterrupt = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置操作文件回调。正在压缩或解压某文件时触发
|
||||
*
|
||||
* @param fileCallback 回调接口
|
||||
*/
|
||||
public void setFileCallback(CallbackArg<File> fileCallback) {
|
||||
this.fileCallback = fileCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置进度回调
|
||||
*
|
||||
* @param progressCallback 回调接口
|
||||
*/
|
||||
public void setProgressCallback(CallbackArg<Double> progressCallback) {
|
||||
this.progressCallback = progressCallback;
|
||||
}
|
||||
}
|
||||
238
src/main/java/com/imyeyu/compress/AbstractRunner.java
Normal file
238
src/main/java/com/imyeyu/compress/AbstractRunner.java
Normal file
@@ -0,0 +1,238 @@
|
||||
package com.imyeyu.compress;
|
||||
|
||||
import com.imyeyu.java.bean.CallbackArg;
|
||||
import com.imyeyu.utils.OS;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* 抽象压缩执行器
|
||||
*
|
||||
* @author 夜雨
|
||||
* @since 2024-06-30 18:09
|
||||
*/
|
||||
public abstract class AbstractRunner implements OS.FileSystem {
|
||||
|
||||
/** 文件处理回调 */
|
||||
@Setter
|
||||
protected CallbackArg<File> fileCallback;
|
||||
|
||||
/** 进度回调 */
|
||||
@Setter
|
||||
protected CallbackArg<Double> progressCallback;
|
||||
|
||||
/** 中断标记 */
|
||||
protected boolean isInterrupt = false;
|
||||
|
||||
/** 暂停标记 */
|
||||
protected boolean isPause = false;
|
||||
|
||||
/** 暂停锁 */
|
||||
protected final Object pauseLock = new Object();
|
||||
|
||||
/** 总字节数 */
|
||||
private long progressTotalBytes = -1L;
|
||||
|
||||
/** 当前已处理字节数 */
|
||||
private long progressBytes = 0L;
|
||||
|
||||
/** 暂停任务 */
|
||||
public void pause() {
|
||||
isPause = true;
|
||||
}
|
||||
|
||||
/** 恢复任务 */
|
||||
public void start() {
|
||||
isPause = false;
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/** 中断任务 */
|
||||
public void interrupt() {
|
||||
isInterrupt = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化字节进度
|
||||
*
|
||||
* @param totalBytes 总字节数
|
||||
*/
|
||||
protected void initByteProgress(long totalBytes) {
|
||||
progressBytes = 0L;
|
||||
progressTotalBytes = totalBytes;
|
||||
}
|
||||
|
||||
/** 重置进度状态 */
|
||||
protected void resetProgress() {
|
||||
progressBytes = 0L;
|
||||
progressTotalBytes = -1L;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行暂停检查
|
||||
*
|
||||
* @throws InterruptedException 等待恢复时被中断
|
||||
*/
|
||||
protected void awaitIfPaused() throws InterruptedException {
|
||||
if (!isPause) {
|
||||
return;
|
||||
}
|
||||
synchronized (pauseLock) {
|
||||
while (isPause) {
|
||||
pauseLock.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否已经中断
|
||||
*
|
||||
* @throws IOException 操作已中断
|
||||
*/
|
||||
protected void ensureRunning() throws IOException {
|
||||
if (isInterrupt) {
|
||||
throw new IOException("操作已中断");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发文件回调
|
||||
*
|
||||
* @param file 当前处理的文件
|
||||
*/
|
||||
protected void handleFile(File file) {
|
||||
if (fileCallback != null) {
|
||||
fileCallback.handler(file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发进度回调
|
||||
*
|
||||
* @param currentBytes 当前已处理字节数
|
||||
* @param totalBytes 总字节数
|
||||
*/
|
||||
protected void handleProgress(long currentBytes, long totalBytes) {
|
||||
if (progressCallback == null || totalBytes < 1L) {
|
||||
return;
|
||||
}
|
||||
double progress = Math.min(1D, currentBytes * 1D / totalBytes);
|
||||
progressCallback.handler(progress);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加已处理字节数并回调
|
||||
*
|
||||
* @param bytes 本次新增字节数
|
||||
*/
|
||||
protected void handleTransferred(long bytes) {
|
||||
if (bytes < 1L) {
|
||||
return;
|
||||
}
|
||||
progressBytes += bytes;
|
||||
handleProgress(progressBytes, progressTotalBytes);
|
||||
}
|
||||
|
||||
/** 将进度推进到完成态 */
|
||||
protected void finishProgress() {
|
||||
if (progressCallback != null) {
|
||||
progressCallback.handler(1D);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制数据流并更新进度
|
||||
*
|
||||
* @param fromStream 输入流
|
||||
* @param toStream 输出流
|
||||
* @return 已复制字节数
|
||||
* @throws Exception 复制失败
|
||||
*/
|
||||
protected long transfer(InputStream fromStream, OutputStream toStream) throws Exception {
|
||||
return transfer(fromStream, toStream, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制数据流
|
||||
*
|
||||
* @param fromStream 输入流
|
||||
* @param toStream 输出流
|
||||
* @param countProgress 是否统计进度
|
||||
* @return 已复制字节数
|
||||
* @throws Exception 复制失败
|
||||
*/
|
||||
protected long transfer(InputStream fromStream, OutputStream toStream, boolean countProgress) throws Exception {
|
||||
byte[] buffer = new byte[8192];
|
||||
long total = 0L;
|
||||
int length;
|
||||
while ((length = fromStream.read(buffer)) != -1) {
|
||||
awaitIfPaused();
|
||||
ensureRunning();
|
||||
toStream.write(buffer, 0, length);
|
||||
total += length;
|
||||
if (countProgress) {
|
||||
handleTransferred(length);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个关闭时不关闭原始流的输入流包装
|
||||
*
|
||||
* @param inputStream 原始输入流
|
||||
* @return 包装后的输入流
|
||||
*/
|
||||
protected InputStream nonClosing(InputStream inputStream) {
|
||||
return new FilterInputStream(inputStream) {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个关闭时不关闭原始流的输出流包装
|
||||
*
|
||||
* @param outputStream 原始输出流
|
||||
* @return 包装后的输出流
|
||||
*/
|
||||
protected OutputStream nonClosing(OutputStream outputStream) {
|
||||
return new FilterOutputStream(outputStream) {
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
flush();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化归档条目名称
|
||||
*
|
||||
* @param entryName 条目名称
|
||||
* @return 规范化后的名称
|
||||
*/
|
||||
protected String normalizeEntryName(String entryName) {
|
||||
if (entryName == null || entryName.isBlank()) {
|
||||
throw new IllegalArgumentException("条目名称不能为空");
|
||||
}
|
||||
String normalized = entryName.replace('\\', '/');
|
||||
while (normalized.startsWith("/")) {
|
||||
normalized = normalized.substring(1);
|
||||
}
|
||||
if (normalized.isBlank()) {
|
||||
throw new IllegalArgumentException("条目名称不能为空");
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,10 @@ package com.imyeyu.compress;
|
||||
|
||||
import com.imyeyu.io.IO;
|
||||
import com.imyeyu.java.ref.Ref;
|
||||
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
@@ -15,16 +19,16 @@ import java.io.InputStream;
|
||||
public enum CompressType {
|
||||
|
||||
/** 7z */
|
||||
Z7(Z7Compressor.class, Z7Decompressor.class, -0x51),
|
||||
Z7(Z7Compressor.class, Z7Decompressor.class),
|
||||
|
||||
/** Zip */
|
||||
ZIP(ZipCompressor.class, ZipDecompressor.class, 0x504B0304),
|
||||
ZIP(ZipCompressor.class, ZipDecompressor.class),
|
||||
|
||||
/** Gzip */
|
||||
GZIP(GZipCompressor.class, GZipDecompressor.class, -0x74F7F8),
|
||||
GZIP(GZipCompressor.class, GZipDecompressor.class),
|
||||
|
||||
/** tar */
|
||||
TAR(TarCompressor.class, TarDecompressor.class, 0x776F7264);
|
||||
/** Tar */
|
||||
TAR(TarCompressor.class, TarDecompressor.class);
|
||||
|
||||
/** 压缩类 */
|
||||
final Class<? extends Compressor> compressorType;
|
||||
@@ -32,13 +36,9 @@ public enum CompressType {
|
||||
/** 解压类 */
|
||||
final Class<? extends Decompressor> decompressorType;
|
||||
|
||||
/** 文件头标记 */
|
||||
final int headHex;
|
||||
|
||||
CompressType(Class<? extends Compressor> compressorType, Class<? extends Decompressor> decompressorType, int headHex) {
|
||||
CompressType(Class<? extends Compressor> compressorType, Class<? extends Decompressor> decompressorType) {
|
||||
this.compressorType = compressorType;
|
||||
this.decompressorType = decompressorType;
|
||||
this.headHex = headHex;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,28 +62,31 @@ public enum CompressType {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件获取解压操作对象。将会读取文件头解析算法类型
|
||||
* 根据文件获取解压操作对象。会读取文件头识别压缩格式
|
||||
*
|
||||
* @param file 文件
|
||||
* @return 解压操作对象
|
||||
* @throws UnsupportedOperationException 不支持的文件
|
||||
* @throws Exception 实例化失败
|
||||
* @throws Exception 实例化失败
|
||||
*/
|
||||
public static Decompressor fromFile(File file) throws Exception {
|
||||
InputStream is = IO.getInputStream(file);
|
||||
byte[] head = new byte[4];
|
||||
if (-1 == is.read(head)) {
|
||||
throw new UnsupportedOperationException("not support file");
|
||||
}
|
||||
is.close();
|
||||
int headHex = 0;
|
||||
for (byte b : head) {
|
||||
headHex <<= 8;
|
||||
headHex |= b;
|
||||
}
|
||||
for (CompressType type : values()) {
|
||||
if (type.headHex == headHex) {
|
||||
return type.getDecompressor();
|
||||
try (InputStream inputStream = IO.getInputStream(file)) {
|
||||
byte[] head = new byte[512];
|
||||
int length = inputStream.read(head);
|
||||
if (length == -1) {
|
||||
throw new UnsupportedOperationException("not support file");
|
||||
}
|
||||
if (SevenZFile.matches(head, length)) {
|
||||
return Z7.getDecompressor();
|
||||
}
|
||||
if (ZipArchiveInputStream.matches(head, length)) {
|
||||
return ZIP.getDecompressor();
|
||||
}
|
||||
if (GzipCompressorInputStream.matches(head, length)) {
|
||||
return GZIP.getDecompressor();
|
||||
}
|
||||
if (TarArchiveInputStream.matches(head, length)) {
|
||||
return TAR.getDecompressor();
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException("not support headHex");
|
||||
|
||||
@@ -1,14 +1,47 @@
|
||||
package com.imyeyu.compress;
|
||||
|
||||
import com.imyeyu.io.IO;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* 抽象压缩器
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2024-06-30 10:34
|
||||
*/
|
||||
public abstract class Compressor extends AbstractCompressor {
|
||||
public abstract class Compressor extends AbstractRunner {
|
||||
|
||||
public abstract void run(String fromPath, File toFile) throws Exception;
|
||||
/**
|
||||
* 将指定路径下的文件压缩到目标文件
|
||||
*
|
||||
* @param fromPath 源路径
|
||||
* @param toFile 目标压缩文件
|
||||
* @throws Exception 压缩失败
|
||||
*/
|
||||
public void run(String fromPath, File toFile) throws Exception {
|
||||
try (OutputStream outputStream = IO.getOutputStream(toFile)) {
|
||||
run(fromPath, outputStream);
|
||||
outputStream.flush();
|
||||
} catch (Exception exception) {
|
||||
if (isInterrupt) {
|
||||
IO.destroy(toFile);
|
||||
}
|
||||
throw exception;
|
||||
}
|
||||
if (isInterrupt) {
|
||||
IO.destroy(toFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定路径下的文件压缩到输出流
|
||||
* 输出流由调用方管理
|
||||
*
|
||||
* @param fromPath 源路径
|
||||
* @param toStream 目标输出流
|
||||
* @throws Exception 压缩失败
|
||||
*/
|
||||
public abstract void run(String fromPath, OutputStream toStream) throws Exception;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,38 @@
|
||||
package com.imyeyu.compress;
|
||||
|
||||
import com.imyeyu.io.IO;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 抽象解压
|
||||
* 抽象解压器
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2024-06-30 18:02
|
||||
*/
|
||||
public abstract class Decompressor extends AbstractCompressor {
|
||||
public abstract class Decompressor extends AbstractRunner {
|
||||
|
||||
/**
|
||||
* 执行解压
|
||||
* 将压缩文件解压到目标目录
|
||||
*
|
||||
* @param fromFile 来源压缩文件
|
||||
* @param toPath 解压路径
|
||||
* @param fromFile 源压缩文件
|
||||
* @param toPath 目标目录
|
||||
* @throws Exception 解压失败
|
||||
*/
|
||||
public abstract void run(File fromFile, String toPath) throws Exception;
|
||||
public void run(File fromFile, String toPath) throws Exception {
|
||||
try (InputStream inputStream = IO.getInputStream(fromFile)) {
|
||||
run(inputStream, toPath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将压缩输入流解压到目标目录
|
||||
* 输入流由调用方管理
|
||||
*
|
||||
* @param fromStream 源压缩输入流
|
||||
* @param toPath 目标目录
|
||||
* @throws Exception 解压失败
|
||||
*/
|
||||
public abstract void run(InputStream fromStream, String toPath) throws Exception;
|
||||
}
|
||||
|
||||
@@ -7,54 +7,44 @@ import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Gzip 压缩器
|
||||
* 当前实现保持与原行为一致,实际输出为 tar.gz
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2024-06-30 19:40
|
||||
*/
|
||||
public class GZipCompressor extends Compressor {
|
||||
|
||||
@Override
|
||||
public void run(String fromPath, File toFile) throws Exception {
|
||||
List<File> files = IO.listFile(new File(fromPath));
|
||||
public void run(String fromPath, OutputStream toStream) throws Exception {
|
||||
File fromFile = new File(fromPath);
|
||||
List<File> files = IO.listFile(fromFile);
|
||||
String basePath = files.getFirst().getParentFile().getAbsolutePath();
|
||||
|
||||
OutputStream os = IO.getOutputStream(toFile);
|
||||
BufferedOutputStream byteOS = new BufferedOutputStream(os);
|
||||
GzipCompressorOutputStream gzipOS = new GzipCompressorOutputStream(byteOS);
|
||||
TarArchiveOutputStream tarOS = new TarArchiveOutputStream(gzipOS);
|
||||
|
||||
TarArchiveEntry tarEntry;
|
||||
for (int i = 0, total = files.size(); i < total; i++) {
|
||||
String name = files.get(i).getAbsolutePath().substring(basePath.length() + 1);
|
||||
tarEntry = new TarArchiveEntry(files.get(i), name.replaceAll("\\\\", "/"));
|
||||
tarOS.putArchiveEntry(tarEntry);
|
||||
tarOS.write(IO.toBytes(files.get(i)));
|
||||
tarOS.closeArchiveEntry();
|
||||
|
||||
if (isPause) {
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.wait();
|
||||
initByteProgress(IO.calcSize(fromFile));
|
||||
try (
|
||||
GzipCompressorOutputStream gzipOutputStream = new GzipCompressorOutputStream(new BufferedOutputStream(nonClosing(toStream)));
|
||||
TarArchiveOutputStream tarOutputStream = new TarArchiveOutputStream(gzipOutputStream)
|
||||
) {
|
||||
for (File sourceFile : files) {
|
||||
String name = sourceFile.getAbsolutePath().substring(basePath.length() + 1);
|
||||
TarArchiveEntry tarEntry = new TarArchiveEntry(sourceFile, normalizeEntryName(name));
|
||||
tarOutputStream.putArchiveEntry(tarEntry);
|
||||
try (InputStream inputStream = IO.getInputStream(sourceFile)) {
|
||||
transfer(inputStream, tarOutputStream);
|
||||
}
|
||||
tarOutputStream.closeArchiveEntry();
|
||||
handleFile(sourceFile);
|
||||
}
|
||||
if (fileCallback != null) {
|
||||
fileCallback.handler(toFile);
|
||||
}
|
||||
if (progressCallback != null) {
|
||||
progressCallback.handler(1D * i / total);
|
||||
}
|
||||
if (isInterrupt) {
|
||||
break;
|
||||
}
|
||||
tarOutputStream.finish();
|
||||
gzipOutputStream.finish();
|
||||
finishProgress();
|
||||
} finally {
|
||||
resetProgress();
|
||||
}
|
||||
tarOS.finish();
|
||||
tarOS.close();
|
||||
gzipOS.finish();
|
||||
gzipOS.close();
|
||||
byteOS.flush();
|
||||
byteOS.close();
|
||||
os.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,12 @@ import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Gzip 解压器
|
||||
* 当前实现保持与原行为一致,实际按 tar.gz 解压
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2024-06-30 19:47
|
||||
*/
|
||||
@@ -16,51 +20,63 @@ public class GZipDecompressor extends Decompressor {
|
||||
|
||||
@Override
|
||||
public void run(File fromFile, String toPath) throws Exception {
|
||||
InputStream is = IO.getInputStream(fromFile);
|
||||
GzipCompressorInputStream gzipIS = new GzipCompressorInputStream(is);
|
||||
TarArchiveInputStream tarIS = new TarArchiveInputStream(gzipIS);
|
||||
initByteProgress(readTotalSize(fromFile));
|
||||
try {
|
||||
super.run(fromFile, toPath);
|
||||
} finally {
|
||||
resetProgress();
|
||||
}
|
||||
}
|
||||
|
||||
int total = 0;
|
||||
{
|
||||
@Override
|
||||
public void run(InputStream fromStream, String toPath) throws Exception {
|
||||
try (
|
||||
GzipCompressorInputStream gzipInputStream = new GzipCompressorInputStream(nonClosing(fromStream));
|
||||
TarArchiveInputStream tarInputStream = new TarArchiveInputStream(gzipInputStream)
|
||||
) {
|
||||
TarArchiveEntry entry;
|
||||
while ((entry = tarIS.getNextEntry()) != null) {
|
||||
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()) {
|
||||
total++;
|
||||
totalSize += entry.getSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
tarIS.close();
|
||||
is.close();
|
||||
|
||||
is = IO.getInputStream(fromFile);
|
||||
tarIS = new TarArchiveInputStream(is);
|
||||
TarArchiveEntry entry;
|
||||
for (int i = 0; (entry = tarIS.getNextEntry()) != null; i++) {
|
||||
String path = IO.fitPath(toPath) + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
IO.dir(path);
|
||||
} else {
|
||||
File toFile = IO.file(path);
|
||||
IO.toFile(toFile, tarIS);
|
||||
|
||||
if (fileCallback != null) {
|
||||
fileCallback.handler(toFile);
|
||||
}
|
||||
}
|
||||
if (isPause) {
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.wait();
|
||||
}
|
||||
}
|
||||
if (progressCallback != null && total != -1) {
|
||||
progressCallback.handler(1D * i / total);
|
||||
}
|
||||
if (isInterrupt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tarIS.close();
|
||||
gzipIS.close();
|
||||
is.close();
|
||||
return totalSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,56 +6,39 @@ import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tar 压缩器
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2024-06-30 19:48
|
||||
*/
|
||||
public class TarCompressor extends Compressor {
|
||||
|
||||
@Override
|
||||
public void run(String fromPath, File toFile) throws Exception {
|
||||
List<File> files = IO.listFile(new File(fromPath));
|
||||
public void run(String fromPath, OutputStream toStream) throws Exception {
|
||||
File fromFile = new File(fromPath);
|
||||
List<File> files = IO.listFile(fromFile);
|
||||
String basePath = files.getFirst().getParentFile().getAbsolutePath();
|
||||
|
||||
OutputStream os = IO.getOutputStream(toFile);
|
||||
BufferedOutputStream byteOS = new BufferedOutputStream(os);
|
||||
TarArchiveOutputStream tarOS = new TarArchiveOutputStream(byteOS);
|
||||
|
||||
TarArchiveEntry tarEntry;
|
||||
for (int i = 0, total = files.size(); i < total; i++) {
|
||||
String name = files.get(i).getAbsolutePath().substring(basePath.length() + 1);
|
||||
tarEntry = new TarArchiveEntry(files.get(i), name.replaceAll("\\\\", "/"));
|
||||
tarOS.putArchiveEntry(tarEntry);
|
||||
tarOS.write(IO.toBytes(files.get(i)));
|
||||
tarOS.closeArchiveEntry();
|
||||
|
||||
if (isPause) {
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.wait();
|
||||
initByteProgress(IO.calcSize(fromFile));
|
||||
try (TarArchiveOutputStream tarOutputStream = new TarArchiveOutputStream(new BufferedOutputStream(nonClosing(toStream)))) {
|
||||
for (File sourceFile : files) {
|
||||
String name = sourceFile.getAbsolutePath().substring(basePath.length() + 1);
|
||||
TarArchiveEntry tarEntry = new TarArchiveEntry(sourceFile, normalizeEntryName(name));
|
||||
tarOutputStream.putArchiveEntry(tarEntry);
|
||||
try (InputStream inputStream = IO.getInputStream(sourceFile)) {
|
||||
transfer(inputStream, tarOutputStream);
|
||||
}
|
||||
tarOutputStream.closeArchiveEntry();
|
||||
handleFile(sourceFile);
|
||||
}
|
||||
if (fileCallback != null) {
|
||||
fileCallback.handler(toFile);
|
||||
}
|
||||
if (progressCallback != null) {
|
||||
progressCallback.handler(1D * i / total);
|
||||
}
|
||||
if (isInterrupt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tarOS.finish();
|
||||
tarOS.close();
|
||||
byteOS.flush();
|
||||
byteOS.close();
|
||||
os.flush();
|
||||
os.close();
|
||||
|
||||
if (isInterrupt) {
|
||||
IO.destroy(toFile);
|
||||
tarOutputStream.finish();
|
||||
finishProgress();
|
||||
} finally {
|
||||
resetProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,11 @@ import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Tar 解压器
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2024-06-30 19:48
|
||||
*/
|
||||
@@ -15,49 +18,56 @@ public class TarDecompressor extends Decompressor {
|
||||
|
||||
@Override
|
||||
public void run(File fromFile, String toPath) throws Exception {
|
||||
InputStream is = IO.getInputStream(fromFile);
|
||||
TarArchiveInputStream tarIS = new TarArchiveInputStream(is);
|
||||
initByteProgress(readTotalSize(fromFile));
|
||||
try {
|
||||
super.run(fromFile, toPath);
|
||||
} finally {
|
||||
resetProgress();
|
||||
}
|
||||
}
|
||||
|
||||
int total = 0;
|
||||
{
|
||||
@Override
|
||||
public void run(InputStream fromStream, String toPath) throws Exception {
|
||||
try (TarArchiveInputStream tarInputStream = new TarArchiveInputStream(nonClosing(fromStream))) {
|
||||
TarArchiveEntry entry;
|
||||
while ((entry = tarIS.getNextEntry()) != null) {
|
||||
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); TarArchiveInputStream tarInputStream = new TarArchiveInputStream(inputStream)) {
|
||||
TarArchiveEntry entry;
|
||||
while ((entry = tarInputStream.getNextEntry()) != null) {
|
||||
if (!entry.isDirectory()) {
|
||||
total++;
|
||||
totalSize += entry.getSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
tarIS.close();
|
||||
is.close();
|
||||
|
||||
is = IO.getInputStream(fromFile);
|
||||
tarIS = new TarArchiveInputStream(is);
|
||||
TarArchiveEntry entry;
|
||||
for (int i = 0; (entry = tarIS.getNextEntry()) != null; i++) {
|
||||
String path = IO.fitPath(toPath) + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
IO.dir(path);
|
||||
} else {
|
||||
File toFile = IO.file(path);
|
||||
IO.toFile(toFile, tarIS);
|
||||
|
||||
if (fileCallback != null) {
|
||||
fileCallback.handler(toFile);
|
||||
}
|
||||
}
|
||||
if (isPause) {
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.wait();
|
||||
}
|
||||
}
|
||||
if (progressCallback != null && total != -1) {
|
||||
progressCallback.handler(1D * i / total);
|
||||
}
|
||||
if (isInterrupt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tarIS.close();
|
||||
is.close();
|
||||
return totalSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,46 +5,81 @@ 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 {
|
||||
|
||||
@Override
|
||||
public void run(String fromPath, File toFile) throws Exception {
|
||||
List<File> files = IO.listFile(new File(fromPath));
|
||||
String basePath = files.getFirst().getParentFile().getAbsolutePath();
|
||||
|
||||
SevenZOutputFile out = new SevenZOutputFile(toFile);
|
||||
SevenZArchiveEntry entry;
|
||||
for (int i = 0, total = files.size(); i < total; i++) {
|
||||
String name = files.get(i).getAbsolutePath().substring(basePath.length() + 1);
|
||||
entry = out.createArchiveEntry(files.get(i), name.replaceAll("\\\\", "/"));
|
||||
out.putArchiveEntry(entry);
|
||||
out.write(IO.toBytes(files.get(i)));
|
||||
out.closeArchiveEntry();
|
||||
|
||||
if (isPause) {
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.wait();
|
||||
}
|
||||
}
|
||||
if (fileCallback != null) {
|
||||
fileCallback.handler(toFile);
|
||||
}
|
||||
if (progressCallback != null) {
|
||||
progressCallback.handler(1D * i / total);
|
||||
}
|
||||
if (isInterrupt) {
|
||||
break;
|
||||
public void run(String fromPath, OutputStream toStream) throws Exception {
|
||||
Path tempFile = Files.createTempFile("timi-compress-", ".7z");
|
||||
try {
|
||||
run(fromPath, tempFile.toFile());
|
||||
try (InputStream inputStream = Files.newInputStream(tempFile)) {
|
||||
transfer(inputStream, toStream, false);
|
||||
toStream.flush();
|
||||
}
|
||||
} finally {
|
||||
Files.deleteIfExists(tempFile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String fromPath, File toFile) throws Exception {
|
||||
File fromFile = new File(fromPath);
|
||||
List<File> 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();
|
||||
}
|
||||
out.close();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,14 @@ 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
|
||||
*/
|
||||
@@ -14,44 +20,98 @@ public class Z7Decompressor extends Decompressor {
|
||||
|
||||
@Override
|
||||
public void run(File fromFile, String toPath) throws Exception {
|
||||
toPath = new File(toPath).getAbsolutePath() + SEP;
|
||||
|
||||
int total = 0;
|
||||
if (progressCallback != null) {
|
||||
SevenZFile file = SevenZFile.builder().setFile(fromFile).get();
|
||||
try (file) {
|
||||
while (file.getNextEntry() != null) {
|
||||
total++;
|
||||
}
|
||||
}
|
||||
initByteProgress(readTotalSize(fromFile));
|
||||
try {
|
||||
super.run(fromFile, toPath);
|
||||
} finally {
|
||||
resetProgress();
|
||||
}
|
||||
SevenZFile file = SevenZFile.builder().setFile(fromFile).get();
|
||||
SevenZArchiveEntry entry;
|
||||
for (int i = 0; (entry = file.getNextEntry()) != null; i++) {
|
||||
if (entry.isDirectory()) {
|
||||
IO.dir(IO.fitPath(toPath) + entry.getName());
|
||||
} else {
|
||||
File toFile = IO.file(toPath + entry.getName());
|
||||
byte[] buffer = new byte[(int) entry.getSize()];
|
||||
file.read(buffer, 0, buffer.length);
|
||||
IO.toFile(toFile, buffer);
|
||||
}
|
||||
|
||||
if (fileCallback != null) {
|
||||
fileCallback.handler(toFile);
|
||||
@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 (isPause) {
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.wait();
|
||||
}
|
||||
if (processed) {
|
||||
finishProgress();
|
||||
}
|
||||
if (progressCallback != null && total != -1) {
|
||||
progressCallback.handler(1D * i / total);
|
||||
}
|
||||
if (isInterrupt) {
|
||||
} 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);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取压缩包解压总字节数
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,57 +4,40 @@ import com.imyeyu.io.IO;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* Zip 压缩器
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2024-06-30 19:46
|
||||
*/
|
||||
public class ZipCompressor extends Compressor {
|
||||
|
||||
@Override
|
||||
public void run(String fromPath, File toFile) throws Exception {
|
||||
List<File> files = IO.listFile(new File(fromPath));
|
||||
public void run(String fromPath, OutputStream toStream) throws Exception {
|
||||
File fromFile = new File(fromPath);
|
||||
List<File> files = IO.listFile(fromFile);
|
||||
String basePath = files.getFirst().getParentFile().getAbsolutePath();
|
||||
|
||||
OutputStream os = IO.getOutputStream(toFile);
|
||||
BufferedOutputStream byteOS = new BufferedOutputStream(os);
|
||||
ZipOutputStream zipOS = new ZipOutputStream(byteOS);
|
||||
|
||||
for (int i = 0, total = files.size(); i < total; i++) {
|
||||
String name = files.get(i).getAbsolutePath().substring(basePath.length() + 1);
|
||||
ZipEntry zipEntry = new ZipEntry(name.replaceAll("\\\\", "/"));
|
||||
zipOS.putNextEntry(zipEntry);
|
||||
zipOS.write(IO.toBytes(files.get(i)));
|
||||
zipOS.closeEntry();
|
||||
|
||||
if (isPause) {
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.wait();
|
||||
initByteProgress(IO.calcSize(fromFile));
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(nonClosing(toStream)))) {
|
||||
for (File sourceFile : files) {
|
||||
String name = sourceFile.getAbsolutePath().substring(basePath.length() + 1);
|
||||
zipOutputStream.putNextEntry(new ZipEntry(normalizeEntryName(name)));
|
||||
try (InputStream inputStream = IO.getInputStream(sourceFile)) {
|
||||
transfer(inputStream, zipOutputStream);
|
||||
}
|
||||
zipOutputStream.closeEntry();
|
||||
handleFile(sourceFile);
|
||||
}
|
||||
if (fileCallback != null) {
|
||||
fileCallback.handler(toFile);
|
||||
}
|
||||
if (progressCallback != null) {
|
||||
progressCallback.handler(1D * i / total);
|
||||
}
|
||||
if (isInterrupt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
zipOS.finish();
|
||||
zipOS.close();
|
||||
byteOS.flush();
|
||||
byteOS.close();
|
||||
os.flush();
|
||||
os.close();
|
||||
|
||||
if (isInterrupt) {
|
||||
IO.destroy(toFile);
|
||||
zipOutputStream.finish();
|
||||
finishProgress();
|
||||
} finally {
|
||||
resetProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,16 @@ package com.imyeyu.compress;
|
||||
import com.imyeyu.io.IO;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* Zip 解压器
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2024-06-30 19:47
|
||||
*/
|
||||
@@ -15,42 +20,63 @@ public class ZipDecompressor extends Decompressor {
|
||||
|
||||
@Override
|
||||
public void run(File fromFile, String toPath) throws Exception {
|
||||
ZipFile zip = new ZipFile(fromFile);
|
||||
|
||||
Enumeration<? extends ZipEntry> entries = zip.entries();
|
||||
int total = 0;
|
||||
while (entries.hasMoreElements()) {
|
||||
if (!entries.nextElement().isDirectory()) {
|
||||
total++;
|
||||
}
|
||||
initByteProgress(readTotalSize(fromFile));
|
||||
try {
|
||||
super.run(fromFile, toPath);
|
||||
} finally {
|
||||
resetProgress();
|
||||
}
|
||||
|
||||
entries = zip.entries();
|
||||
ZipEntry entry;
|
||||
for (int i = 0; entries.hasMoreElements(); i++) {
|
||||
entry = entries.nextElement();
|
||||
if (entry.isDirectory()) {
|
||||
IO.dir(IO.fitPath(toPath) + entry.getName());
|
||||
} else {
|
||||
File toFile = IO.file(IO.fitPath(toPath) + entry.getName());
|
||||
IO.toFile(toFile, zip.getInputStream(entry));
|
||||
|
||||
if (fileCallback != null) {
|
||||
fileCallback.handler(toFile);
|
||||
}
|
||||
}
|
||||
if (isPause) {
|
||||
synchronized (pauseLock) {
|
||||
pauseLock.wait();
|
||||
}
|
||||
}
|
||||
if (progressCallback != null) {
|
||||
progressCallback.handler(1D * i / total);
|
||||
}
|
||||
if (isInterrupt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
zip.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(InputStream fromStream, String toPath) throws Exception {
|
||||
try (ZipInputStream zipInputStream = new ZipInputStream(nonClosing(fromStream))) {
|
||||
ZipEntry entry;
|
||||
boolean processed = false;
|
||||
while ((entry = zipInputStream.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(zipInputStream, outputStream);
|
||||
outputStream.flush();
|
||||
}
|
||||
handleFile(toFile);
|
||||
processed = true;
|
||||
}
|
||||
zipInputStream.closeEntry();
|
||||
}
|
||||
if (processed) {
|
||||
finishProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取压缩包解压总字节数
|
||||
*
|
||||
* @param fromFile 压缩文件
|
||||
* @return 总字节数,未知时返回 -1
|
||||
* @throws Exception 读取失败
|
||||
*/
|
||||
private long readTotalSize(File fromFile) throws Exception {
|
||||
long totalSize = 0L;
|
||||
try (ZipFile zipFile = new ZipFile(fromFile)) {
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
long size = entry.getSize();
|
||||
if (size < 0L) {
|
||||
return -1L;
|
||||
}
|
||||
totalSize += size;
|
||||
}
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user