Java 7zip压缩太大
Java 7zip compression is too big
我有一个 Java 程序,它搜索包含昨天日期的文件夹并将其压缩为 7zip 文件并在最后删除它。现在我注意到我的程序生成的 7zip 存档文件太大了。当我使用像 7-Zip 文件管理器这样的程序来压缩我的文件时,它会生成一个 5 kb 大的存档,而我的程序会为相同的文件(具有 873 kb 大小)生成一个 737 kb 大的存档。现在恐怕我的程序不会将其压缩为 7zip 文件,而是压缩为普通的 zip 文件。有没有办法更改我的代码中的某些内容,以便它生成一个较小的 7zip 文件,就像 7-Zip 文件管理器那样?
package SevenZip;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
public class SevenZipUtils {
public static void main(String[] args) throws InterruptedException, IOException {
String sourceFolder = "C:/Users/Ferid/Documents/Dates/";
String outputZipFile = "/Users/Ferid/Documents/Dates";
int sleepTime = 0;
compress(sleepTime, outputZipFile, sourceFolder);
}
public static boolean deleteDirectory(File directory, int sleepTime) throws InterruptedException {
if (directory.exists()) {
File[] files = directory.listFiles();
if (null != files) {
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteDirectory(files[i], sleepTime);
System.out.println("Folder deleted: " + files[i]);
} else {
files[i].delete();
System.out.println("File deleted: " + files[i]);
}
}
}
}
TimeUnit.SECONDS.sleep(sleepTime);
return (directory.delete());
}
public static void compress(int sleepTime, String outputZipFile, String sourceFolder)
throws IOException, InterruptedException {
// finds folder of yesterdays date
final Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1); // date of yesterday
String timeStamp = new SimpleDateFormat("yyyyMMdd").format(cal.getTime()); // format the date
System.out.println("Yesterday was " + timeStamp);
if (sourceFolder.endsWith("/")) { // add yesterday folder to sourcefolder path
sourceFolder = sourceFolder + timeStamp;
} else {
sourceFolder = sourceFolder + "/" + timeStamp;
}
if (outputZipFile.endsWith("/")) { // add yesterday folder name to outputZipFile path
outputZipFile = outputZipFile + " " + timeStamp + ".7z";
} else {
outputZipFile = outputZipFile + "/" + timeStamp + ".7z";
}
File file = new File(sourceFolder);
if (file.exists()) {
try (SevenZOutputFile out = new SevenZOutputFile(new File(outputZipFile))) {
addToArchiveCompression(out, file, ".");
System.out.println("Files sucessfully compressed");
deleteDirectory(new File(sourceFolder), sleepTime);
}
} else {
System.out.println("Folder does not exist");
}
}
private static void addToArchiveCompression(SevenZOutputFile out, File file, String dir) throws IOException {
String name = dir + File.separator + file.getName();
if (file.isFile()) {
SevenZArchiveEntry entry = out.createArchiveEntry(file, name);
out.putArchiveEntry(entry);
FileInputStream in = new FileInputStream(file);
byte[] b = new byte[1024];
int count = 0;
while ((count = in.read(b)) > 0) {
out.write(b, 0, count);
}
out.closeArchiveEntry();
in.close();
System.out.println("File added: " + file.getName());
} else if (file.isDirectory()) {
File[] children = file.listFiles();
if (children != null) {
for (File child : children) {
addToArchiveCompression(out, child, name);
}
}
System.out.println("Directory added: " + file.getName());
} else {
System.out.println(file.getName() + " is not supported");
}
}
}
我正在使用 Apache Commons Compress library
编辑:这是一个 link,我从中获得了一些 Apache Commons Compress 代码。
Commons Compress 正在为每个存档条目在容器文件中启动一个新块。注意这里的块计数器:
不是您所希望的答案,但文档说它不支持 "solid compression" - 将多个文件写入一个块。请参阅文档中的第 5 段 here。
快速浏览了一下,发现了一些其他 Java 支持 LZMA 压缩的库,但我无法在 7-Zip 的父容器文件格式中找到可以这样做的库。也许其他人知道替代方案...
听起来像普通的 zip 文件格式(例如通过 ZipOutputStream)不是一个选项?
我没有足够的代表发表评论所以这是我的想法:
- 我没看到您在哪里设置压缩比,所以
SevenZOutputFile
可能没有使用(或非常低的)压缩。正如@CristiFati 所说,压缩差异很奇怪,尤其是对于文本文件
- 如 @df778899 所述,不支持固体压缩,这是实现最佳压缩率的方式,因此您将无法像 7z 命令行那样好
也就是说,如果 zip 确实不是一个选项,您最后的选择可能是 call the proper command line directly within your program。
如果纯 7z 不是强制性的,另一种选择是使用类似 "tgz" 的格式来模拟固体压缩:首先将所有文件压缩为非压缩文件(例如 tar 格式,或没有压缩的 zip 文件),然后 使用标准 Java Deflate 算法以 zip 模式压缩该单个文件。当然,只有当该格式被使用它的其他进程识别时,这才是可行的。
改用7-Zip file archiver,它将832 KB
文件轻松压缩到26.0 KB
:
- 获取其Jar and SDK.
- 选择 LZMA 压缩
.java
个相关文件。
- 在项目属性中添加
Run
参数:e "D:\2017ASP.pdf" "D:\2017ASP.7z"
,e
代表encode
,"input path"
"output path"
.
- 运行 项目 [LzmaAlone.java].
结果
案例 1(.pdf 文件):
从 33,969 KB
到 24,645 KB
.
案例2(.docx文件):
从 832 KB
到 26.0 KB
.
我有一个 Java 程序,它搜索包含昨天日期的文件夹并将其压缩为 7zip 文件并在最后删除它。现在我注意到我的程序生成的 7zip 存档文件太大了。当我使用像 7-Zip 文件管理器这样的程序来压缩我的文件时,它会生成一个 5 kb 大的存档,而我的程序会为相同的文件(具有 873 kb 大小)生成一个 737 kb 大的存档。现在恐怕我的程序不会将其压缩为 7zip 文件,而是压缩为普通的 zip 文件。有没有办法更改我的代码中的某些内容,以便它生成一个较小的 7zip 文件,就像 7-Zip 文件管理器那样?
package SevenZip;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
public class SevenZipUtils {
public static void main(String[] args) throws InterruptedException, IOException {
String sourceFolder = "C:/Users/Ferid/Documents/Dates/";
String outputZipFile = "/Users/Ferid/Documents/Dates";
int sleepTime = 0;
compress(sleepTime, outputZipFile, sourceFolder);
}
public static boolean deleteDirectory(File directory, int sleepTime) throws InterruptedException {
if (directory.exists()) {
File[] files = directory.listFiles();
if (null != files) {
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteDirectory(files[i], sleepTime);
System.out.println("Folder deleted: " + files[i]);
} else {
files[i].delete();
System.out.println("File deleted: " + files[i]);
}
}
}
}
TimeUnit.SECONDS.sleep(sleepTime);
return (directory.delete());
}
public static void compress(int sleepTime, String outputZipFile, String sourceFolder)
throws IOException, InterruptedException {
// finds folder of yesterdays date
final Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1); // date of yesterday
String timeStamp = new SimpleDateFormat("yyyyMMdd").format(cal.getTime()); // format the date
System.out.println("Yesterday was " + timeStamp);
if (sourceFolder.endsWith("/")) { // add yesterday folder to sourcefolder path
sourceFolder = sourceFolder + timeStamp;
} else {
sourceFolder = sourceFolder + "/" + timeStamp;
}
if (outputZipFile.endsWith("/")) { // add yesterday folder name to outputZipFile path
outputZipFile = outputZipFile + " " + timeStamp + ".7z";
} else {
outputZipFile = outputZipFile + "/" + timeStamp + ".7z";
}
File file = new File(sourceFolder);
if (file.exists()) {
try (SevenZOutputFile out = new SevenZOutputFile(new File(outputZipFile))) {
addToArchiveCompression(out, file, ".");
System.out.println("Files sucessfully compressed");
deleteDirectory(new File(sourceFolder), sleepTime);
}
} else {
System.out.println("Folder does not exist");
}
}
private static void addToArchiveCompression(SevenZOutputFile out, File file, String dir) throws IOException {
String name = dir + File.separator + file.getName();
if (file.isFile()) {
SevenZArchiveEntry entry = out.createArchiveEntry(file, name);
out.putArchiveEntry(entry);
FileInputStream in = new FileInputStream(file);
byte[] b = new byte[1024];
int count = 0;
while ((count = in.read(b)) > 0) {
out.write(b, 0, count);
}
out.closeArchiveEntry();
in.close();
System.out.println("File added: " + file.getName());
} else if (file.isDirectory()) {
File[] children = file.listFiles();
if (children != null) {
for (File child : children) {
addToArchiveCompression(out, child, name);
}
}
System.out.println("Directory added: " + file.getName());
} else {
System.out.println(file.getName() + " is not supported");
}
}
}
我正在使用 Apache Commons Compress library
编辑:这是一个 link,我从中获得了一些 Apache Commons Compress 代码。
Commons Compress 正在为每个存档条目在容器文件中启动一个新块。注意这里的块计数器:
不是您所希望的答案,但文档说它不支持 "solid compression" - 将多个文件写入一个块。请参阅文档中的第 5 段 here。
快速浏览了一下,发现了一些其他 Java 支持 LZMA 压缩的库,但我无法在 7-Zip 的父容器文件格式中找到可以这样做的库。也许其他人知道替代方案...
听起来像普通的 zip 文件格式(例如通过 ZipOutputStream)不是一个选项?
我没有足够的代表发表评论所以这是我的想法:
- 我没看到您在哪里设置压缩比,所以
SevenZOutputFile
可能没有使用(或非常低的)压缩。正如@CristiFati 所说,压缩差异很奇怪,尤其是对于文本文件 - 如 @df778899 所述,不支持固体压缩,这是实现最佳压缩率的方式,因此您将无法像 7z 命令行那样好
也就是说,如果 zip 确实不是一个选项,您最后的选择可能是 call the proper command line directly within your program。
如果纯 7z 不是强制性的,另一种选择是使用类似 "tgz" 的格式来模拟固体压缩:首先将所有文件压缩为非压缩文件(例如 tar 格式,或没有压缩的 zip 文件),然后 使用标准 Java Deflate 算法以 zip 模式压缩该单个文件。当然,只有当该格式被使用它的其他进程识别时,这才是可行的。
改用7-Zip file archiver,它将832 KB
文件轻松压缩到26.0 KB
:
- 获取其Jar and SDK.
- 选择 LZMA 压缩
.java
个相关文件。 - 在项目属性中添加
Run
参数:e "D:\2017ASP.pdf" "D:\2017ASP.7z"
,e
代表encode
,"input path"
"output path"
. - 运行 项目 [LzmaAlone.java].
结果
案例 1(.pdf 文件):
从 33,969 KB
到 24,645 KB
.
案例2(.docx文件):
从 832 KB
到 26.0 KB
.