Elegant Way to Count Number of Files in a Zip Archive

file handlingjava

I need to count the number of files in several zip archives for error checking. I've found several answers on SO but nothing elegant. I currently have the following code which works but it's not pretty:

File[] fileListing = new File("ZipFiles").listFiles();
int numberOfFilesInAllZipArchives = 0;
for(File file : fileListing)
{
    ZipFile zf = new ZipFile(file.getName());
    numberOfFilesInAllZipArchives += zf.size();
    zf.close();
}

Is there any way to get around creating an object for each zip file or making this process more streamlined?

Thanks!

Best Answer

The only thing I see inelegant about your implementation is intertwining the file listing work, the zip file opening/closing work, and the counting work. (Do you have another issue with it?)

Solution 1: Use Java's try-with-resources block to automate the file closing work thanks to ZipFile being AutoCloseable:

...
try (ZipFile zf = new ZipFile(file) {
  numberOfFilesInAllZipArchives += zf.size();
}
...

Solution 2: In Groovy, separate out the file listing work (and add filename filtering):

import java.util.zip.ZipFile

def dir = new File('Downloads')
def num = 0
dir.eachFileMatch(~/.*\.zip/) { f ->
    def z = new ZipFile(f)
    num += z.size()
    z.close()
}
println num

Solution 3: Also separate ZipFile open/closing work using Groovy's "with" idiom, adding a zipFileWith(closure) method to the class File:

import java.util.zip.ZipFile

File.metaClass.zipFileWith = { closure ->
    def zf = new ZipFile(delegate)
    try {
        closure(zf)
    } finally {
        zf?.close()
    }
}

def dir = new File('Downloads')
def num = 0
dir.eachFileMatch(~/.*\.zip/) { file ->
    file.zipFileWith { zf -> num += zf.size() }
}
println num

Solution 4: Add an eachZipFile(closure) method to the class File:

import java.util.zip.ZipFile

File.metaClass.eachZipFile = { closure ->
    delegate.eachFileMatch(~/.*\.zip/) { file ->
        def zf = new ZipFile(file)
        try {
            closure(zf)
        } finally {
            zf?.close()
        }
    }
}

def dir = new File('Downloads')
def num = 0
dir.eachZipFile { zf -> num += zf.size() }
println num