从ZipInputStream获取特定文件

Jil*_*ils 7 java file-io groovy inputstream zipinputstream

我可以通过ZipInputStream,但在开始迭代之前,我想获得迭代期间需要的特定文件.我怎样才能做到这一点?

ZipInputStream zin = new ZipInputStream(myInputStream)
while ((entry = zin.getNextEntry()) != null)
 {
    println entry.getName()
}
Run Code Online (Sandbox Code Playgroud)

Ian*_*rts 6

如果myInputStream您使用的 来自磁盘上的真实文件,那么您可以简单地使用java.util.zip.ZipFile它,它由 a 支持RandomAccessFile并提供按名称直接访问 zip 条目。但是,如果您所拥有的只是一个InputStream(例如,如果您在从网络套接字或类似设备接收到的流时直接处理流),那么您将不得不进行自己的缓冲。

您可以将流复制到临时文件,然后使用打开该文件ZipFile,或者如果您事先知道数据的最大大小(例如,对于预先声明其的 HTTP 请求Content-Length),您可以使用 aBufferedInputStream在内存中缓冲它,直到您已找到所需的条目。

BufferedInputStream bufIn = new BufferedInputStream(myInputStream);
bufIn.mark(contentLength);
ZipInputStream zipIn = new ZipInputStream(bufIn);
boolean foundSpecial = false;
while ((entry = zin.getNextEntry()) != null) {
  if("special.txt".equals(entry.getName())) {
    // do whatever you need with the special entry
    foundSpecial = true;
    break;
  }
}

if(foundSpecial) {
  // rewind
  bufIn.reset();
  zipIn = new ZipInputStream(bufIn);
  // ....
}
Run Code Online (Sandbox Code Playgroud)

(我自己还没有测试过这段代码,您可能会发现有必要CloseShieldInputStreambufIn和第一个之间使用类似 commons-io 的东西zipIn,以允许第一个 zip 流关闭而不关闭底层,bufIn然后再回滚它)。


Rob*_*tie 5

使用ZipEntry上的getName()方法获取所需的文件.

ZipInputStream zin = new ZipInputStream(myInputStream)
String myFile = "foo.txt";
while ((entry = zin.getNextEntry()) != null)
{
    if (entry.getName().equals(myFileName)) {
        // process your file
        // stop looking for your file - you've already found it
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

从Java 7开始,如果您只需要一个文件并且有一个要读取的文件,那么最好使用ZipFile而不是ZipStream:

ZipFile zfile = new ZipFile(aFile);
String myFile = "foo.txt";
ZipEntry entry = zfile.getEntry(myFile);
if (entry) {
     // process your file           
}
Run Code Online (Sandbox Code Playgroud)