package com.example;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.file.*;
import java.time.*;
import java.util.*;
import java.util.stream.*;
import net.lingala.zip4j.ZipFile;
import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;
public class CompressionRunner {
public static void main(String[] args) throws Exception {
Path inputZip = Paths.get("/home/zhouweixiang/addSecret/zip-generator/target/output/map_data_0.zip");
Path unzipDir = Paths.get("now");
Path lz4File = Paths.get("backup.lz4");
Path lz4UnzipDir = Paths.get("unzipped_lz4");
Instant totalStart = Instant.now();
// 1. 解压 ZIP (Zip4j + ZStandard)
if (shouldSkip("1. ZIP 解压", unzipDir)) {
System.out.println("⚠️ 已跳过:目标目录已存在文件");
} else {
Instant start = Instant.now();
System.out.println("1. 开始解压 ZIP 文件...");
unzipWithZip4j(inputZip, unzipDir);
System.out.println("⏱️ ZIP 解压耗时: " + Duration.between(start, Instant.now()).getSeconds() + " 秒");
}
// 2. 压缩为 LZ4(带原始长度信息)
if (shouldSkip("2. LZ4 压缩", lz4File)) {
System.out.println("⚠️ 已跳过:目标文件已存在");
} else {
Instant start = Instant.now();
System.out.println("\n2. 开始压缩文件夹为 LZ4...");
compressToLZ4(unzipDir, lz4File);
System.out.println("⏱️ LZ4 压缩耗时: " + Duration.between(start, Instant.now()).getSeconds() + " 秒");
}
// 3. 解压 LZ4(使用原始长度解压)
if (shouldSkip("3. LZ4 解压", lz4UnzipDir)) {
System.out.println("⚠️ 已跳过:目标目录已存在文件");
} else {
Instant start = Instant.now();
System.out.println("\n3. 开始解压 LZ4 文件...");
decompressLZ4(lz4File, lz4UnzipDir);
System.out.println("⏱️ LZ4 解压耗时: " + Duration.between(start, Instant.now()).getSeconds() + " 秒");
}
Instant totalEnd = Instant.now();
System.out.println("\n✅ 全部任务完成!");
System.out.println("总耗时: " + Duration.between(totalStart, totalEnd).getSeconds() + " 秒");
}
private static boolean shouldSkip(String step, Path targetPath) throws IOException {
if (Files.exists(targetPath)) {
if (Files.isDirectory(targetPath)) {
try (Stream<Path> list = Files.list(targetPath)) {
if (list.findFirst().isPresent()) {
return true;
}
}
} else if (Files.isRegularFile(targetPath)) {
return true;
}
}
return false;
}
private static void unzipWithZip4j(Path zipPath, Path outputDir) throws Exception {
try (ZipFile zipFile = new ZipFile(zipPath.toFile())) {
zipFile.extractAll(outputDir.toString());
System.out.println("✅ ZIP 解压完成: " + outputDir);
}
}
private static void compressToLZ4(Path sourceDir, Path lz4File) throws IOException {
LZ4Factory factory = LZ4Factory.fastestInstance();
LZ4Compressor compressor = factory.highCompressor();
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(lz4File.toFile()))) {
List<Path> files = new ArrayList<>();
try (Stream<Path> walk = Files.walk(sourceDir)) {
walk.filter(path -> !Files.isDirectory(path)).forEach(files::add);
}
int total = files.size();
int count = 0;
for (Path path : files) {
byte[] data = Files.readAllBytes(path);
// 压缩
byte[] compressed = new byte[compressor.maxCompressedLength(data.length)];
int compressedLength = compressor.compress(data, 0, data.length, compressed, 0, compressed.length);
// 写入原始长度(4 字节)
byte[] lengthBytes = ByteBuffer.allocate(4).putInt(data.length).array();
out.write(lengthBytes);
// 写入压缩后长度(4 字节)
byte[] compressedLengthBytes = ByteBuffer.allocate(4).putInt(compressedLength).array();
out.write(compressedLengthBytes);
// 写入压缩数据
out.write(compressed, 0, compressedLength);
System.out.print("📦");
updateProgress(++count, total);
}
}
System.out.println("\n✅ LZ4 压缩完成: " + lz4File);
}
private static void decompressLZ4(Path lz4File, Path outputDir) throws IOException {
LZ4Factory factory = LZ4Factory.fastestInstance();
LZ4FastDecompressor decompressor = factory.fastDecompressor();
try (InputStream in = new BufferedInputStream(new FileInputStream(lz4File.toFile()))) {
byte[] lengthBuffer = new byte[4];
while (in.read(lengthBuffer) == 4) {
int originalLength = ByteBuffer.wrap(lengthBuffer).getInt();
if (in.read(lengthBuffer) != 4) {
throw new IOException("压缩长度数据不完整");
}
int compressedLength = ByteBuffer.wrap(lengthBuffer).getInt();
byte[] compressedData = new byte[compressedLength];
if (in.read(compressedData) != compressedLength) {
throw new IOException("压缩数据不完整");
}
byte[] restored = new byte[originalLength];
decompressor.decompress(compressedData, 0, restored, 0, originalLength);
Path tempFile = outputDir.resolve("restored.bin");
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile.toFile()))) {
out.write(restored);
}
}
}
System.out.println("✅ LZ4 解压完成: " + outputDir.resolve("restored.bin"));
}
// ✅ 辅助方法:按指定长度读取
private static byte[] readFully(InputStream in, int length) throws IOException {
byte[] buffer = new byte[length];
int offset = 0;
while (offset < length) {
int read = in.read(buffer, offset, length - offset);
if (read == -1) {
throw new IOException("压缩数据不完整");
}
offset += read;
}
return buffer;
}
private static void updateProgress(int current, int total) {
int percent = (int) ((double) current / total * 100);
int barLength = 20;
int filledLength = (int) ((double) percent / 100 * barLength);
String filled = new String(new char[filledLength]).replace('\0', '=');
String empty = new String(new char[barLength - filledLength]).replace('\0', '-');
String bar = filled + empty;
System.out.printf("\r[%s] %d%%", bar, percent);
}
}
package com.example;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.file.*;
import java.time.*;
import java.util.*;
import java.util.stream.*;
import net.lingala.zip4j.ZipFile;
import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;
public class CompressionRunner {
public static void main(String[] args) throws Exception {
Path inputZip = Paths.get("/home/zhouweixiang/addSecret/zip-generator/target/output/map_data_0.zip");
Path unzipDir = Paths.get("now");
Path lz4File = Paths.get("backup.lz4");
Path lz4UnzipDir = Paths.get("unzipped_lz4");
Instant totalStart = Instant.now();
// 1. 解压 ZIP (Zip4j + ZStandard)
if (shouldSkip("1. ZIP 解压", unzipDir)) {
System.out.println("⚠️ 已跳过:目标目录已存在文件");
} else {
Instant start = Instant.now();
System.out.println("1. 开始解压 ZIP 文件...");
unzipWithZip4j(inputZip, unzipDir);
System.out.println("⏱️ ZIP 解压耗时: " + Duration.between(start, Instant.now()).getSeconds() + " 秒");
}
// 2. 压缩为 LZ4(带原始长度信息)
if (shouldSkip("2. LZ4 压缩", lz4File)) {
System.out.println("⚠️ 已跳过:目标文件已存在");
} else {
Instant start = Instant.now();
System.out.println("\n2. 开始压缩文件夹为 LZ4...");
compressToLZ4(unzipDir, lz4File);
System.out.println("⏱️ LZ4 压缩耗时: " + Duration.between(start, Instant.now()).getSeconds() + " 秒");
}
// 3. 解压 LZ4(使用原始长度解压)
if (shouldSkip("3. LZ4 解压", lz4UnzipDir)) {
System.out.println("⚠️ 已跳过:目标目录已存在文件");
} else {
Instant start = Instant.now();
System.out.println("\n3. 开始解压 LZ4 文件...");
decompressLZ4(lz4File, lz4UnzipDir);
System.out.println("⏱️ LZ4 解压耗时: " + Duration.between(start, Instant.now()).getSeconds() + " 秒");
}
Instant totalEnd = Instant.now();
System.out.println("\n✅ 全部任务完成!");
System.out.println("总耗时: " + Duration.between(totalStart, totalEnd).getSeconds() + " 秒");
}
private static boolean shouldSkip(String step, Path targetPath) throws IOException {
if (Files.exists(targetPath)) {
if (Files.isDirectory(targetPath)) {
try (Stream<Path> list = Files.list(targetPath)) {
if (list.findFirst().isPresent()) {
return true;
}
}
} else if (Files.isRegularFile(targetPath)) {
return true;
}
}
return false;
}
private static void unzipWithZip4j(Path zipPath, Path outputDir) throws Exception {
try (ZipFile zipFile = new ZipFile(zipPath.toFile())) {
zipFile.extractAll(outputDir.toString());
System.out.println("✅ ZIP 解压完成: " + outputDir);
}
}
private static void compressToLZ4(Path sourceDir, Path lz4File) throws IOException {
LZ4Factory factory = LZ4Factory.fastestInstance();
LZ4Compressor compressor = factory.highCompressor();
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(lz4File.toFile()))) {
List<Path> files = new ArrayList<>();
try (Stream<Path> walk = Files.walk(sourceDir)) {
walk.filter(path -> !Files.isDirectory(path)).forEach(files::add);
}
int total = files.size();
int count = 0;
for (Path path : files) {
byte[] data = Files.readAllBytes(path);
// 压缩
byte[] compressed = new byte[compressor.maxCompressedLength(data.length)];
int compressedLength = compressor.compress(data, 0, data.length, compressed, 0, compressed.length);
// 写入原始长度(4 字节)
byte[] lengthBytes = ByteBuffer.allocate(4).putInt(data.length).array();
out.write(lengthBytes);
// 写入压缩后长度(4 字节)
byte[] compressedLengthBytes = ByteBuffer.allocate(4).putInt(compressedLength).array();
out.write(compressedLengthBytes);
// 写入压缩数据
out.write(compressed, 0, compressedLength);
System.out.print("📦");
updateProgress(++count, total);
}
}
System.out.println("\n✅ LZ4 压缩完成: " + lz4File);
}
private static void decompressLZ4(Path lz4File, Path outputDir) throws IOException {
LZ4Factory factory = LZ4Factory.fastestInstance();
LZ4FastDecompressor decompressor = factory.fastDecompressor();
try (InputStream in = new BufferedInputStream(new FileInputStream(lz4File.toFile()))) {
byte[] lengthBuffer = new byte[4];
while (in.read(lengthBuffer) == 4) {
int originalLength = ByteBuffer.wrap(lengthBuffer).getInt();
if (in.read(lengthBuffer) != 4) {
throw new IOException("压缩长度数据不完整");
}
int compressedLength = ByteBuffer.wrap(lengthBuffer).getInt();
byte[] compressedData = new byte[compressedLength];
if (in.read(compressedData) != compressedLength) {
throw new IOException("压缩数据不完整");
}
byte[] restored = new byte[originalLength];
decompressor.decompress(compressedData, 0, restored, 0, originalLength);
Path tempFile = outputDir.resolve("restored.bin");
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile.toFile()))) {
out.write(restored);
}
}
}
System.out.println("✅ LZ4 解压完成: " + outputDir.resolve("restored.bin"));
}
// ✅ 辅助方法:按指定长度读取
private static byte[] readFully(InputStream in, int length) throws IOException {
byte[] buffer = new byte[length];
int offset = 0;
while (offset < length) {
int read = in.read(buffer, offset, length - offset);
if (read == -1) {
throw new IOException("压缩数据不完整");
}
offset += read;
}
return buffer;
}
private static void updateProgress(int current, int total) {
int percent = (int) ((double) current / total * 100);
int barLength = 20;
int filledLength = (int) ((double) percent / 100 * barLength);
String filled = new String(new char[filledLength]).replace('\0', '=');
String empty = new String(new char[barLength - filledLength]).replace('\0', '-');
String bar = filled + empty;
System.out.printf("\r[%s] %d%%", bar, percent);
}
}
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.5.1:java (default-cli) on project fastzip-test: An exception occurred while executing the Java class. unzipped_lz4/restored.bin (没有那个文件或目录) -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.5.1:java (default-cli) on project fastzip-test: An exception occurred while executing the Java class. unzipped_lz4/restored.bin (没有那个文件或目录)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:215)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:566)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.apache.maven.plugin.MojoExecutionException: An exception occurred while executing the Java class. unzipped_lz4/restored.bin (没有那个文件或目录)
at org.codehaus.mojo.exec.ExecJavaMojo.execute (ExecJavaMojo.java:349)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:566)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: java.io.FileNotFoundException: unzipped_lz4/restored.bin (没有那个文件或目录)
at java.io.FileOutputStream.open0 (Native Method)
at java.io.FileOutputStream.open (FileOutputStream.java:298)
at java.io.FileOutputStream.<init> (FileOutputStream.java:237)
at java.io.FileOutputStream.<init> (FileOutputStream.java:187)
at com.example.CompressionRunner.decompressLZ4 (CompressionRunner.java:145)
at com.example.CompressionRunner.main (CompressionRunner.java:50)
at org.codehaus.mojo.exec.ExecJavaMojo.doMain (ExecJavaMojo.java:371)
at org.codehaus.mojo.exec.ExecJavaMojo.doExec (ExecJavaMojo.java:360)
at org.codehaus.mojo.exec.ExecJavaMojo.lambda$execute$0 (ExecJavaMojo.java:280)
at java.lang.Thread.run (Thread.java:829)
[ERROR]
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException