javafile-iogroovyinputstreamzipinputstream

Getting specific file from ZipInputStream


I can go through ZipInputStream, but before starting the iteration I want to get a specific file that I need during the iteration. How can I do that?

ZipInputStream zin = new ZipInputStream(myInputStream)
while ((entry = zin.getNextEntry()) != null)
 {
    println entry.getName()
}

Solution

  • If the myInputStream you're working with comes from a real file on disk then you can simply use java.util.zip.ZipFile instead, which is backed by a RandomAccessFile and provides direct access to the zip entries by name. But if all you have is an InputStream (e.g. if you're processing the stream directly on receipt from a network socket or similar) then you'll have to do your own buffering.

    You could copy the stream to a temporary file, then open that file using ZipFile, or if you know the maximum size of the data in advance (e.g. for an HTTP request that declares its Content-Length up front) you could use a BufferedInputStream to buffer it in memory until you've found the required entry.

    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);
      // ....
    }
    

    (I haven't tested this code myself, you may find it's necessary to use something like the commons-io CloseShieldInputStream in between the bufIn and the first zipIn, to allow the first zip stream to close without closing the underlying bufIn before you've rewound it).