自从我完成Java I / O以来已经有一段时间了,而且我不知道使用Zip和GZip文件的最新“正确”方法。我不一定需要一个完整的工作演示 - 我主要是寻找合适的接口和方法。是的,我可以查看任何关于此的随机教程,但性能是一个问题(这些文件可能会变得很大),我确实关心使用最好的工具。
我将要实施的基本流程:
输入文件可能会被压缩和存档多次。例如,“完全提取”应该采用以下任何输入(我无法控制这些输入),并留下foo.txt
:
foo.txt.gz
foo.txt.zip
foo.txt.gz.zip
foo.txt.zip.gz
foo.txt.gz.gz.gz.zip.gz.zip.zip.gz.gz
然后,我可能会留下foo.txt
,bar.mp3
,baz.exe
- 所以我只想将它们全部添加到一个带有通用名称的新zip文件中。
答案 0 :(得分:9)
不要将所有这些未压缩的数据保存在内存中,否则可能会耗尽堆空间。您需要在解压缩时将数据流式传输到文件,然后在您想要创建最终的zip文件时将其从文件中重新流式传输。
我之前没有完成压缩文件,但这里有一个示例,说明如何解压缩 gzipped 文件:
import java.io.*;
import java.util.zip.*;
//unzipping a gzipped file
GZIPInputStream in = null;
OutputStream out = null;
try {
in = new GZIPInputStream(new FileInputStream("file.txt.gz"));
out = new FileOutputStream("file.txt");
byte[] buf = new byte[1024 * 4];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (in != null)
try {
in.close();
}
catch (IOException ignore) {
}
if (out != null)
try {
out.close();
}
catch (IOException ignore) {
}
}
答案 1 :(得分:8)
请注意,下面建议的库TrueZip已被TrueVFS.
取代我发现TrueZIP library很有用。它允许您将存档文件视为仅仅是另一个文件系统并使用熟悉的Java I / O API。
与java.util.zip API不同,TrueZIP提供对存档内容的随机访问,因此文件大小不应该是一个问题。如果我没记错的话,它会检测存档文件,而不是在将它们放入存档时对它们进行冗余压缩。
引用TrueZIP页面:
TrueZIP API为众所周知的类File,FileInputStream和FileOutputStream提供了直接替换。这种设计使得TrueZIP非常易于使用:为大多数客户端应用程序启用存档所需的只是为de.schlichtherle.io包添加一些import语句,并在需要时添加一些类型转换。
现在,您可以简单地处理存档文件,例如路径名中的目录。例如,路径名“archive.zip/readme”解决ZIP文件“archive.zip”中的归档条目“readme”。请注意,文件名后缀是完全可配置的,TrueZIP会自动检测误报,并将其恢复为普通文件或目录。这是递归工作的,因此存档文件甚至可以包含在另一个存档文件中,例如“outer.zip/inner.zip/readme”。
答案 2 :(得分:3)
在某处可能有一个图书馆可以让这很容易。
但是,如果没有,您仍然可以使用java.util.zip classes ...使用ZipFile
或ZipInputStream
以及ZipEntry
进行艰难的操作拉链。
GZIPInputStream
可以为gzip包装FileInputStream
,请记住gzip仅适用于单个文件。
两种类型的InputStream也有各自的OutputStreams。
不幸的是,虽然我知道这些课程,但我从未真正使用,所以我不能再为你提供建议。
编辑:Zip函数似乎没有任何方法可以将新文件添加到zip文件而无需重新创建整个文件。