0

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!

  • Given the structure of a Zip archive it doesn't get a whole lot prettier; the only thing faster is to examine the "Central Directory" byte for byte and that tends to be something Java makes intentionally difficult. – KeithS Apr 17 '15 at 22:45
  • That's what I was afraid of. Is there another language that is better for things (file manipulation) like this? – D. Gibbs Apr 18 '15 at 0:35
  • There is nothing inelegant in the use of objects; or more specifically, if you think there is, then Java definitely isn't the language for you. Maybe you still think using new is a slow, expensive thing to do - that was true in the nineties, but isn't anymore. These days it usually amounts to incrementing a memory reference somewhere. – Kilian Foth Apr 18 '15 at 6:36
2

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
  • Excellent Answer. #1 is more elegant than what I have. – D. Gibbs Apr 19 '15 at 2:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.