5

I am trying to find a file within a zip file and get it as an InputStream. So this is what I am doing to get it so far and I am not certain if I am doing it correctly.

Here is a sample as the original is slightly longer but this is the main component...

public InputStream Search_Image(String file_located, ZipInputStream zip) 
    throws IOException {
    for (ZipEntry zip_e = zip.getNextEntry(); zip_e != null ; zip_e = zip.getNextEntry()) {
        if (file_located.equals(zip_e.getName())) {
            return zip;
        }
        if (zip_e.isDirectory()) {
            Search_Image(file_located, zip); 
        }
    }
    return null;
}

Now the main problem I am facing is that The ZipInputStream in Search_Image is the same as the original component of the ZipInputStream...

if(zip_e.isDirectory()) {
    //"zip" is the same as the original I need a change here to find folders again.
    Search_Image(file_located, zip); 
}

Now for the question, how do you get the ZipInputStream as the new zip_entry? Also please add in if I did anything wrong in my method as my logic with this class is still lacking.

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
Donkey King
  • 105
  • 1
  • 2
  • 8

3 Answers3

9

You should use the class ZipFile without worrying yourself with an input stream if you don't need it yet.

ZipFile file = new ZipFile("file.zip");
ZipInputStream zis = searchImage("foo.png", file);

public InputStream searchImage(String name, ZipFile file) {
  for (ZipEntry e : Collections.list(file.entries())) {
    if (e.getName().endsWith(name)) {
      return file.getInputStream(e);
    }
  }
  return null;
}

Some facts:

  • you should follow conventions for naming methods and variables in your code (Search_Image is not fine, searchImage is)
  • directories in zip files does not contain any file, they are just entries like everything else so you shouldn't try to recurse into them)
  • you should compare the name you provide by using endsWith(name) because the file could be inside a folder and a filename inside a zip always contains the path
wcmatthysen
  • 445
  • 4
  • 19
Jack
  • 131,802
  • 30
  • 241
  • 343
  • What happens when the image I seek is in a folder with the zip?. I had this as my original method problem was that this doesn't search the directories for the image. – Donkey King Jun 20 '12 at 16:16
  • 2
    because you were using `equals(..)` instead that `endsWith(..)`, take a look at my third point. – Jack Jun 20 '12 at 16:16
5

Accessing to a zip entry using ZipInputStream is clearly not the way to do it as you will need to iterate over the entries to find it which is not a scalable approach because the performance will depend on total amount of entries in your zip file.

To get the best possible performances, you need to use a ZipFile in order to access directly to an entry thanks to the method getEntry(name) whatever the size of your archive.

public InputStream searchImage(String name, ZipFile zipFile) throws IOException {
    // Get the entry by its name
    ZipEntry entry = zipFile.getEntry(name);
    if (entry != null) {
        // The entry could be found
        return zipFile.getInputStream(entry);
    }
    // The entry could not be found
    return null;
}

Please note that the name to provide here is the relative path of your image in the archive using / as path separator so if you want to access to foo.png that is in the directory bar, the expected name will be bar/foo.png.

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
0

Here is my take on this:

ZipFile zipFile = new ZipFile(new File("/path/to/zip/file.zip"));
InputStream inputStream = searchWithinZipArchive("findMe.txt", zipFile);

public InputStream searchWithinZipArchive(String name, ZipFile file) throws Exception {
  Enumeration<? extends ZipEntry> entries = file.entries();
  while(entries.hasMoreElements()){
     ZipEntry zipEntry = entries.nextElement();
      if(zipEntry.getName().toLowerCase().endsWith(name)){
             return file.getInputStream(zipEntry);
      }
  }
  return null;
}
Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
ChaitanyaBhatt
  • 1,158
  • 14
  • 11