简体   繁体   中英

Count the number of files inside an entry of jar file

I'm searching for a way to count the number of files inside an entry of a jar file.

For example, assume I have inside the jar a folder called "myFolder", I want to be able to count the number of files inside of it.

I used the idea from here to get to myFolder, yet I don't know how to get to the files inside.

Here is my code:

private int countFiles() {
    JarFile jf = null;
    int counter = 0;
    try {
        jf = new JarFile(new File(ClassName.class
                .getProtectionDomain().getCodeSource().getLocation().toURI()));
        Enumeration<JarEntry> entries = jf.entries();
        while (entries.hasMoreElements()) {
            JarEntry entry = entries.nextElement();
            if (entry.isDirectory()) {
                if (entry.getName().equals("myFolder/")) {
                    ///////
                }
            }
        }
    } catch (Exception ex) {
        try {
            jf.close();
        } catch (Exception e) {
        }
    }
    return counter;
}

Appreciate the help!

If you want to do this in Java then it might be easier to use the ZIP File System Provider from the NIO2 API.

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;

public class Main {

  public static void main(String[] args) throws IOException {
    Path jarFile = Path.of("path", "to", "file.jar");
    String directoryPath = "/myFolder";

    long fileCount = countFilesInDir(jarFile, directoryPath);
    System.out.println(fileCount);
  }

  public static long countFilesInDir(Path jarFile, String directory) throws IOException {
    try (FileSystem fs = FileSystems.newFileSystem(jarFile)) {
      return Files.list(fs.getPath(directory)).count();
    }
  }
}

If you only want to count regular files then change:

return Files.list(fs.getPath(directory)).count();

To:

return Files.list(directory).filter(Files::isRegularFile).count();

And if you want to count the entries/files recursively then check out the java.nio.file.Files#find(Path,int,BiPredicate,FileVisitOption...) method.


Note : Normally you should close the Stream returned by Files.list or Files.find when done with it, but in this case it should be closed as a consequence of the FileSystem being closed.

Only empty directories in the jar will pass the isDirectory test.
For file entries, directory will be contained in the name

shell> import java.util.jar.JarFile;

JarFile jf = new JarFile(new File("test.jar"));
jf ==> java.util.jar.JarFile@32d992b2

jf.stream().forEach(f -> System.out.println(f.getName()))
META-INF/
META-INF/MANIFEST.MF
dir1/Order.MOVED
dir1/Pet.MOVED
dir1/Tag.MOVED
dir1/User.MOVED
empty/

jf.stream().forEach(f -> { if(f.getName().contains("dir1/")) System.out.println(f.getName()) ;})
dir1/Order.MOVED
dir1/Pet.MOVED
dir1/Tag.MOVED
dir1/User.MOVED
jf.stream().forEach(f -> { if(f.getName().contains("dir1/dir2/")) System.out.println(f.getName()) ;})
dir1/dir2/
dir1/dir2/Pet.MOVED
dir1/dir2/Order.MOVED

Can be used without checking if it's a directory as

while (entries.hasMoreElements()) {
    JarEntry entry = entries.nextElement();
    if (entry.getName().contains("myFolder/")) {
        ///////
    }
}

This should also work

while (entries.hasMoreElements()) {
    JarEntry entry = entries.nextElement();
    if (!entry.isDirectory() && entry.getName().startsWith("myFolder/")) {
        ///////
    }
}

Only empty directories in the jar will be passed to the isDirectory test.
For file entries, directory will be contained in the name

shell> import java.util.jar.JarFile;

JarFile jf = new JarFile(new File("test.jar"));
jf ==> java.util.jar.JarFile@32d992b2

jf.stream().forEach(f -> System.out.println(f.getName()))
META-INF/
META-INF/MANIFEST.MF
dir1/Order.MOVED
dir1/Pet.MOVED
dir1/Tag.MOVED
dir1/User.MOVED
empty/

jf.stream().forEach(f -> { if(f.getName().contains("dir1/")) System.out.println(f.getName()) ;})
dir1/Order.MOVED
dir1/Pet.MOVED
dir1/Tag.MOVED
dir1/User.MOVED
jf.stream().forEach(f -> { if(f.getName().contains("dir1/dir2/")) System.out.println(f.getName()) ;})
dir1/dir2/
dir1/dir2/Pet.MOVED
dir1/dir2/Order.MOVED

Can be used without checking if it's a directory as

while (entries.hasMoreElements()) {
    JarEntry entry = entries.nextElement();
    
        if(entry.getName().contains("myFolder/")) {

            ///////

        }
    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM