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!

3
  • 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, 2015 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, 2015 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. Apr 18, 2015 at 6:36

1 Answer 1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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