在Java中使用Zip和GZip文件

在Java中使用Zip和GZip文件,java,file-io,zip,gzip,Java,File Io,Zip,Gzip,我已经有一段时间没有完成Java I/O了,我不知道使用Zip和GZip文件的最新“正确”方法。我不一定需要一个完整的工作演示-我主要是寻找正确的接口和使用的方法。是的,我可以查阅任何关于这方面的随机教程,但性能是一个问题(这些文件可能会变得很大),我确实关心如何使用最好的工具来完成这项工作 我将实施的基本流程是: 将一组文件(可能是压缩的、gzip的或两者都有)下载到临时文件夹中 将所有提取的文件添加到临时文件夹中的新zip文件中 输入文件可能会被压缩和归档多次。例如,“完全提取”应采用以

我已经有一段时间没有完成Java I/O了,我不知道使用Zip和GZip文件的最新“正确”方法。我不一定需要一个完整的工作演示-我主要是寻找正确的接口和使用的方法。是的,我可以查阅任何关于这方面的随机教程,但性能是一个问题(这些文件可能会变得很大),我确实关心如何使用最好的工具来完成这项工作

我将实施的基本流程是:

  • 将一组文件(可能是压缩的、gzip的或两者都有)下载到临时文件夹中
  • 将所有提取的文件添加到临时文件夹中的新zip文件中
输入文件可能会被压缩和归档多次。例如,“完全提取”应采用以下任何输入(我不控制这些输入),并保留
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文件中

问题:
  • 由于文件大小是一个潜在问题,我应该使用哪些(接口/类/方法)来快速:
    • 解压缩压缩文件
    • 提取gzip文件
    • 写压缩文件
  • 在回写到磁盘之前,是否最好将单个提取的文件保存在内存中?或者
  • 潜在的大文件会让这成为一个坏主意吗

也许有一个图书馆可以让这一切变得简单

然而,如果没有,你仍然可以用艰难的方式来做。。。使用或,与for zip一起使用

可以为gzip包装一个
FileInputStream
,记住gzip只在单个文件上工作

两种类型的输入流也有各自的输出流

不幸的是,虽然我知道这些类,但我从未实际使用过它们,所以我不能给你更多的建议


编辑:Zip函数似乎没有任何方法可以在不重新创建整个文件的情况下向Zip文件添加新文件。

注意,下面建议的库TrueZip已被


我发现这本书很有用。它允许您将归档文件视为另一个文件系统,并使用熟悉的JavaI/OAPI

与java.util.zip API不同,TrueZIP提供了对存档内容的随机访问,因此文件大小不应成为问题。如果我没记错的话,它会检测归档文件,而不会在您将它们放入归档文件时尝试对它们进行冗余压缩

引用TrueZIP页面:

TrueZIP API为众所周知的类File、FileInputStream和FileOutputStream提供了插入式替换。这种设计使TrueZIP使用起来非常简单:要使大多数客户端应用程序能够存档,只需为de.schlichtherle.io包添加一些导入语句,并在需要时添加一些类型转换

现在,您可以简单地处理归档文件,如路径名中的目录。例如,路径名“archive.zip/readme”在zip文件“archive.zip”中寻址归档条目“readme”。请注意,文件名后缀是完全可配置的,TrueZIP会自动检测误报,并将其还原为普通文件或目录。这是递归工作的,因此一个归档文件甚至可能包含在另一个归档文件中,如“outer.zip/inner.zip/readme”


不要在内存中保存所有这些未压缩的数据,否则可能会耗尽堆空间。解压时需要将数据流式输出到文件,然后在创建最终zip文件时从文件流式返回

我以前没有做过压缩文件,但下面是一个示例,演示如何解压缩压缩文件:


谢谢我最终选择了TrueZIP,在经历了一点挫折之后(由于没有摸索),它工作得很好。FWIW,java.util.ZipFile还提供了内存映射随机访问:@reve_etrange您介意更新链接或解释一下您的意思吗?FWIW,这篇文章仍然可以在甲骨文的网站上找到:@StanislavPalatnik可能是部分代码与问题无关的原因;)(顺便说一句,我不是下选程序)catch(IOException e){e.printStackTrace();}最后{if(in!=null)try{in.close();}catch(IOException ignore){}if(out!=null)try{out.close();}catch(IOException ignore){}使用Java 9,这可以简化为
try(InputStream in=new GZIPInputStream(new FileInputStream(“file.txt.gz”);OutputStream out=new FileOutputStream(“file.txt”){in.transferTo(out);}
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) {
       }
}