From 47f1c9520e87912dbbb872ff8c9575eaa41868f2 Mon Sep 17 00:00:00 2001 From: Timi Date: Mon, 14 Jul 2025 15:27:37 +0800 Subject: [PATCH] Initial project --- .gitignore | 130 +++++------------- .idea/.gitignore | 3 + .idea/encodings.xml | 7 + .idea/misc.xml | 14 ++ .idea/uiDesigner.xml | 124 +++++++++++++++++ .idea/vcs.xml | 6 + pom.xml | 56 ++++++++ .../imyeyu/compress/AbstractCompressor.java | 66 +++++++++ .../com/imyeyu/compress/CompressType.java | 91 ++++++++++++ .../java/com/imyeyu/compress/Compressor.java | 14 ++ .../com/imyeyu/compress/Decompressor.java | 21 +++ .../com/imyeyu/compress/GZipCompressor.java | 60 ++++++++ .../com/imyeyu/compress/GZipDecompressor.java | 66 +++++++++ .../com/imyeyu/compress/TarCompressor.java | 61 ++++++++ .../com/imyeyu/compress/TarDecompressor.java | 63 +++++++++ .../com/imyeyu/compress/Z7Compressor.java | 50 +++++++ .../com/imyeyu/compress/Z7Decompressor.java | 57 ++++++++ .../com/imyeyu/compress/ZipCompressor.java | 60 ++++++++ .../com/imyeyu/compress/ZipDecompressor.java | 56 ++++++++ src/test/java/test/ClearTest.java | 21 +++ src/test/java/test/GzipTest.java | 27 ++++ src/test/java/test/TarTest.java | 27 ++++ src/test/java/test/Z7Test.java | 27 ++++ src/test/java/test/ZipTest.java | 27 ++++ testSrc/file.txt | 1 + testSrc/subDir/subFile.txt | 1 + testSrc/subDir/subFile2.txt | 1 + 27 files changed, 1043 insertions(+), 94 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/encodings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/uiDesigner.xml create mode 100644 .idea/vcs.xml create mode 100644 pom.xml create mode 100644 src/main/java/com/imyeyu/compress/AbstractCompressor.java create mode 100644 src/main/java/com/imyeyu/compress/CompressType.java create mode 100644 src/main/java/com/imyeyu/compress/Compressor.java create mode 100644 src/main/java/com/imyeyu/compress/Decompressor.java create mode 100644 src/main/java/com/imyeyu/compress/GZipCompressor.java create mode 100644 src/main/java/com/imyeyu/compress/GZipDecompressor.java create mode 100644 src/main/java/com/imyeyu/compress/TarCompressor.java create mode 100644 src/main/java/com/imyeyu/compress/TarDecompressor.java create mode 100644 src/main/java/com/imyeyu/compress/Z7Compressor.java create mode 100644 src/main/java/com/imyeyu/compress/Z7Decompressor.java create mode 100644 src/main/java/com/imyeyu/compress/ZipCompressor.java create mode 100644 src/main/java/com/imyeyu/compress/ZipDecompressor.java create mode 100644 src/test/java/test/ClearTest.java create mode 100644 src/test/java/test/GzipTest.java create mode 100644 src/test/java/test/TarTest.java create mode 100644 src/test/java/test/Z7Test.java create mode 100644 src/test/java/test/ZipTest.java create mode 100644 testSrc/file.txt create mode 100644 testSrc/subDir/subFile.txt create mode 100644 testSrc/subDir/subFile2.txt diff --git a/.gitignore b/.gitignore index c6d98d1..a263bb0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,98 +1,40 @@ -# ---> JetBrains -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -# ---> Maven target/ -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties -# https://github.com/takari/maven-wrapper#usage-without-binary-jar -.mvn/wrapper/maven-wrapper.jar +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ -# Eclipse m2e generated files -# Eclipse Core -.project -# JDT-specific (Eclipse Java Development Tools) +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated .classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store + +/testOut* diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..fdc35ea --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b4f3e4e --- /dev/null +++ b/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.imyeyu.compress + timi-compress + 0.0.1 + + + true + 21 + 21 + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 21 + 21 + UTF-8 + + + + + + + + com.imyeyu.io + timi-io + 0.0.1 + + + org.apache.commons + commons-compress + 1.26.1 + + + org.tukaani + xz + 1.9 + + + org.junit.jupiter + junit-jupiter-api + 5.10.2 + test + + + diff --git a/src/main/java/com/imyeyu/compress/AbstractCompressor.java b/src/main/java/com/imyeyu/compress/AbstractCompressor.java new file mode 100644 index 0000000..e592565 --- /dev/null +++ b/src/main/java/com/imyeyu/compress/AbstractCompressor.java @@ -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 fileCallback; + + /** 进度回调 */ + protected CallbackArg 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 fileCallback) { + this.fileCallback = fileCallback; + } + + /** + * 设置进度回调 + * + * @param progressCallback 回调接口 + */ + public void setProgressCallback(CallbackArg progressCallback) { + this.progressCallback = progressCallback; + } +} diff --git a/src/main/java/com/imyeyu/compress/CompressType.java b/src/main/java/com/imyeyu/compress/CompressType.java new file mode 100644 index 0000000..db27f55 --- /dev/null +++ b/src/main/java/com/imyeyu/compress/CompressType.java @@ -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 compressorType; + + /** 解压类 */ + final Class decompressorType; + + /** 文件头标记 */ + final int headHex; + + CompressType(Class compressorType, Class 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"); + } +} diff --git a/src/main/java/com/imyeyu/compress/Compressor.java b/src/main/java/com/imyeyu/compress/Compressor.java new file mode 100644 index 0000000..0191c91 --- /dev/null +++ b/src/main/java/com/imyeyu/compress/Compressor.java @@ -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; +} diff --git a/src/main/java/com/imyeyu/compress/Decompressor.java b/src/main/java/com/imyeyu/compress/Decompressor.java new file mode 100644 index 0000000..e21dbbc --- /dev/null +++ b/src/main/java/com/imyeyu/compress/Decompressor.java @@ -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; +} diff --git a/src/main/java/com/imyeyu/compress/GZipCompressor.java b/src/main/java/com/imyeyu/compress/GZipCompressor.java new file mode 100644 index 0000000..e3531cc --- /dev/null +++ b/src/main/java/com/imyeyu/compress/GZipCompressor.java @@ -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 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(); + } +} diff --git a/src/main/java/com/imyeyu/compress/GZipDecompressor.java b/src/main/java/com/imyeyu/compress/GZipDecompressor.java new file mode 100644 index 0000000..09e7632 --- /dev/null +++ b/src/main/java/com/imyeyu/compress/GZipDecompressor.java @@ -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(); + } +} diff --git a/src/main/java/com/imyeyu/compress/TarCompressor.java b/src/main/java/com/imyeyu/compress/TarCompressor.java new file mode 100644 index 0000000..ed0d631 --- /dev/null +++ b/src/main/java/com/imyeyu/compress/TarCompressor.java @@ -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 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); + } + } +} diff --git a/src/main/java/com/imyeyu/compress/TarDecompressor.java b/src/main/java/com/imyeyu/compress/TarDecompressor.java new file mode 100644 index 0000000..e893224 --- /dev/null +++ b/src/main/java/com/imyeyu/compress/TarDecompressor.java @@ -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(); + } +} diff --git a/src/main/java/com/imyeyu/compress/Z7Compressor.java b/src/main/java/com/imyeyu/compress/Z7Compressor.java new file mode 100644 index 0000000..943ffb9 --- /dev/null +++ b/src/main/java/com/imyeyu/compress/Z7Compressor.java @@ -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 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); + } + } +} diff --git a/src/main/java/com/imyeyu/compress/Z7Decompressor.java b/src/main/java/com/imyeyu/compress/Z7Decompressor.java new file mode 100644 index 0000000..c65e73e --- /dev/null +++ b/src/main/java/com/imyeyu/compress/Z7Decompressor.java @@ -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(); + } +} diff --git a/src/main/java/com/imyeyu/compress/ZipCompressor.java b/src/main/java/com/imyeyu/compress/ZipCompressor.java new file mode 100644 index 0000000..2d384ba --- /dev/null +++ b/src/main/java/com/imyeyu/compress/ZipCompressor.java @@ -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 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); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/imyeyu/compress/ZipDecompressor.java b/src/main/java/com/imyeyu/compress/ZipDecompressor.java new file mode 100644 index 0000000..8251601 --- /dev/null +++ b/src/main/java/com/imyeyu/compress/ZipDecompressor.java @@ -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 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(); + } +} \ No newline at end of file diff --git a/src/test/java/test/ClearTest.java b/src/test/java/test/ClearTest.java new file mode 100644 index 0000000..1e1565b --- /dev/null +++ b/src/test/java/test/ClearTest.java @@ -0,0 +1,21 @@ +package test; + +import com.imyeyu.io.IO; +import org.junit.jupiter.api.Test; + +import java.io.File; + +/** + * @author 夜雨 + * @version 2024-06-30 23:54 + */ +public class ClearTest { + + @Test + public void clearTestFiles() throws Exception { + IO.destroy(new File("testOut")); + IO.dir("testOut"); + IO.destroy(new File("testOutDe")); + IO.dir("testOutDe"); + } +} \ No newline at end of file diff --git a/src/test/java/test/GzipTest.java b/src/test/java/test/GzipTest.java new file mode 100644 index 0000000..4efa22a --- /dev/null +++ b/src/test/java/test/GzipTest.java @@ -0,0 +1,27 @@ +package test; + +import com.imyeyu.compress.CompressType; +import com.imyeyu.io.IO; +import org.junit.jupiter.api.Test; + +import java.io.File; + +/** + * @author 夜雨 + * @version 2024-06-30 17:54 + */ +public class GzipTest { + + @Test + public void testCompress() throws Exception { + File out = IO.file("testOut/test.gz"); + CompressType.Z7.getCompressor().run("testSrc", out); + } + + @Test + public void testDecompress() throws Exception { + File in = IO.file("testOut/test.gz"); + File out = IO.dir("testOutDe"); + CompressType.fromFile(in).run(in, out.getAbsolutePath()); + } +} diff --git a/src/test/java/test/TarTest.java b/src/test/java/test/TarTest.java new file mode 100644 index 0000000..12aaffc --- /dev/null +++ b/src/test/java/test/TarTest.java @@ -0,0 +1,27 @@ +package test; + +import com.imyeyu.compress.CompressType; +import com.imyeyu.io.IO; +import org.junit.jupiter.api.Test; + +import java.io.File; + +/** + * @author 夜雨 + * @version 2024-06-30 17:54 + */ +public class TarTest { + + @Test + public void testCompress() throws Exception { + File out = IO.file("testOut/test.tar"); + CompressType.Z7.getCompressor().run("testSrc", out); + } + + @Test + public void testDecompress() throws Exception { + File in = IO.file("testOut/test.tar"); + File out = IO.dir("testOutDe"); + CompressType.fromFile(in).run(in, out.getAbsolutePath()); + } +} diff --git a/src/test/java/test/Z7Test.java b/src/test/java/test/Z7Test.java new file mode 100644 index 0000000..ebf8f26 --- /dev/null +++ b/src/test/java/test/Z7Test.java @@ -0,0 +1,27 @@ +package test; + +import com.imyeyu.compress.CompressType; +import com.imyeyu.io.IO; +import org.junit.jupiter.api.Test; + +import java.io.File; + +/** + * @author 夜雨 + * @version 2024-06-30 10:53 + */ +public class Z7Test { + + @Test + public void testCompress() throws Exception { + File out = IO.file("testOut/test.7z"); + CompressType.Z7.getCompressor().run("testSrc", out); + } + + @Test + public void testDecompress() throws Exception { + File in = IO.file("testOut/test.7z"); + File out = IO.dir("testOutDe"); + CompressType.fromFile(in).run(in, out.getAbsolutePath()); + } +} \ No newline at end of file diff --git a/src/test/java/test/ZipTest.java b/src/test/java/test/ZipTest.java new file mode 100644 index 0000000..a2c8af1 --- /dev/null +++ b/src/test/java/test/ZipTest.java @@ -0,0 +1,27 @@ +package test; + +import com.imyeyu.compress.CompressType; +import com.imyeyu.io.IO; +import org.junit.jupiter.api.Test; + +import java.io.File; + +/** + * @author 夜雨 + * @version 2024-06-30 17:54 + */ +public class ZipTest { + + @Test + public void testCompress() throws Exception { + File out = IO.file("testOut/test.zip"); + CompressType.Z7.getCompressor().run("testSrc", out); + } + + @Test + public void testDecompress() throws Exception { + File in = IO.file("testOut/test.zip"); + File out = IO.dir("testOutDe"); + CompressType.fromFile(in).run(in, out.getAbsolutePath()); + } +} diff --git a/testSrc/file.txt b/testSrc/file.txt new file mode 100644 index 0000000..3ebaf0c --- /dev/null +++ b/testSrc/file.txt @@ -0,0 +1 @@ +file test \ No newline at end of file diff --git a/testSrc/subDir/subFile.txt b/testSrc/subDir/subFile.txt new file mode 100644 index 0000000..fd6ff5b --- /dev/null +++ b/testSrc/subDir/subFile.txt @@ -0,0 +1 @@ +sub file test \ No newline at end of file diff --git a/testSrc/subDir/subFile2.txt b/testSrc/subDir/subFile2.txt new file mode 100644 index 0000000..836abe5 --- /dev/null +++ b/testSrc/subDir/subFile2.txt @@ -0,0 +1 @@ +sub file test2 \ No newline at end of file