Initial project

This commit is contained in:
Timi
2025-07-14 15:27:37 +08:00
parent 063520868e
commit 47f1c9520e
27 changed files with 1043 additions and 94 deletions

View File

@ -0,0 +1,66 @@
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;
}
}

View File

@ -0,0 +1,91 @@
package com.imyeyu.compress;
import com.imyeyu.io.IO;
import com.imyeyu.java.ref.Ref;
import java.io.File;
import java.io.InputStream;
/**
* 压缩算法类型
*
* @author 夜雨
* @version 2024-06-30 18:03
*/
public enum CompressType {
/** 7z */
Z7(Z7Compressor.class, Z7Decompressor.class, -0x51),
/** Zip */
ZIP(ZipCompressor.class, ZipDecompressor.class, 0x504B0304),
/** Gzip */
GZIP(GZipCompressor.class, GZipDecompressor.class, -0x74F7F8),
/** tar */
TAR(TarCompressor.class, TarDecompressor.class, 0x776F7264);
/** 压缩类 */
final Class<? extends Compressor> compressorType;
/** 解压类 */
final Class<? extends Decompressor> decompressorType;
/** 文件头标记 */
final int headHex;
CompressType(Class<? extends Compressor> compressorType, Class<? extends Decompressor> decompressorType, int headHex) {
this.compressorType = compressorType;
this.decompressorType = decompressorType;
this.headHex = headHex;
}
/**
* 获取压缩操作对象
*
* @return 压缩操作对象
* @throws Exception 实例化失败
*/
public Compressor getCompressor() throws Exception {
return Ref.newInstance(compressorType);
}
/**
* 获取解压操作对象
*
* @return 解压操作对象
* @throws Exception 实例化失败
*/
public Decompressor getDecompressor() throws Exception {
return Ref.newInstance(decompressorType);
}
/**
* 根据文件获取解压操作对象。将会读取文件头解析算法类型
*
* @param file 文件
* @return 解压操作对象
* @throws UnsupportedOperationException 不支持的文件
* @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();
}
}
throw new UnsupportedOperationException("not support headHex");
}
}

View File

@ -0,0 +1,14 @@
package com.imyeyu.compress;
import java.io.File;
/**
*
*
* @author 夜雨
* @version 2024-06-30 10:34
*/
public abstract class Compressor extends AbstractCompressor {
public abstract void run(String fromPath, File toFile) throws Exception;
}

View File

@ -0,0 +1,21 @@
package com.imyeyu.compress;
import java.io.File;
/**
* 抽象解压
*
* @author 夜雨
* @version 2024-06-30 18:02
*/
public abstract class Decompressor extends AbstractCompressor {
/**
* 执行解压
*
* @param fromFile 来源压缩文件
* @param toPath 解压路径
* @throws Exception 解压失败
*/
public abstract void run(File fromFile, String toPath) throws Exception;
}

View File

@ -0,0 +1,60 @@
package com.imyeyu.compress;
import com.imyeyu.io.IO;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.util.List;
/**
* @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));
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();
}
}
if (fileCallback != null) {
fileCallback.handler(toFile);
}
if (progressCallback != null) {
progressCallback.handler(1D * i / total);
}
if (isInterrupt) {
break;
}
}
tarOS.finish();
tarOS.close();
gzipOS.finish();
gzipOS.close();
byteOS.flush();
byteOS.close();
os.close();
}
}

View File

@ -0,0 +1,66 @@
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;
/**
* @author 夜雨
* @version 2024-06-30 19:47
*/
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);
int total = 0;
{
TarArchiveEntry entry;
while ((entry = tarIS.getNextEntry()) != null) {
if (!entry.isDirectory()) {
total++;
}
}
}
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();
}
}

View File

@ -0,0 +1,61 @@
package com.imyeyu.compress;
import com.imyeyu.io.IO;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.util.List;
/**
* @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));
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();
}
}
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);
}
}
}

View File

@ -0,0 +1,63 @@
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 java.io.File;
import java.io.InputStream;
/**
* @author 夜雨
* @version 2024-06-30 19:48
*/
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);
int total = 0;
{
TarArchiveEntry entry;
while ((entry = tarIS.getNextEntry()) != null) {
if (!entry.isDirectory()) {
total++;
}
}
}
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();
}
}

View File

@ -0,0 +1,50 @@
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.util.List;
/**
* @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;
}
}
out.close();
if (isInterrupt) {
IO.destroy(toFile);
}
}
}

View File

@ -0,0 +1,57 @@
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;
/**
* @author 夜雨
* @version 2024-06-30 19:42
*/
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++;
}
}
}
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);
}
}
if (isPause) {
synchronized (pauseLock) {
pauseLock.wait();
}
}
if (progressCallback != null && total != -1) {
progressCallback.handler(1D * i / total);
}
if (isInterrupt) {
break;
}
}
file.close();
}
}

View File

@ -0,0 +1,60 @@
package com.imyeyu.compress;
import com.imyeyu.io.IO;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @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));
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();
}
}
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);
}
}
}

View File

@ -0,0 +1,56 @@
package com.imyeyu.compress;
import com.imyeyu.io.IO;
import java.io.File;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* @author 夜雨
* @version 2024-06-30 19:47
*/
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++;
}
}
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();
}
}