Search code examples
javajarclassloader

How do I access the content of folders inside a jar file?


I need to take a look at the names of files inside a specific package. Currently, I'm doing the following:

ClassLoader loader = Thread.currentThread().getContextClassLoader();
URL packageUrl = loader.getResource(getPackage().replace('.', '/'));
File packageDir = new File(packageUrl.getFile());

// Work with the files inside the directory

This actually works just fine in Eclipse, since it doesn't package my application by default. When I run it from a jar file, however, I get a NullPointerException on packageUrl.

So, how do I obtain a list of the contents of a package that's inside a jar? My research suggested using getResourceAsStream, but I'm not quite sure how to explore a directory with an InputStream, if that's even possible.


Solution

  • You could get path to the jar file and open it with ZipInputStream list all the files inside that jar.

    To know the path of the running jar, try using:

    InputStream in = MyClass
                    .class
                    .getProtectionDomain()
                    .getCodeSource()
                    .getLocation()
                    .openStream();
    

    See also: How do I list the files inside a JAR file?

    update

    I've compiled an ran your solution and works perfect:

    C:\java\injar>dir
     El volumen de la unidad C no tiene etiqueta.
     El número de serie del volumen es: 22A8-203B
    
     Directorio de C:\java\injar
    
    21/02/2011  06:23 p.m.    <DIR>          .
    21/02/2011  06:23 p.m.    <DIR>          ..
    21/02/2011  06:23 p.m.             1,752 i18n.jar
    21/02/2011  06:23 p.m.    <DIR>          src
    21/02/2011  06:21 p.m.    <DIR>          x
    
    C:\java\injar>jar -tf i18n.jar
    META-INF/
    META-INF/MANIFEST.MF
    I18n.class
    x/
    x/y/
    x/y/z/
    x/y/z/hola.txt
    
    C:\java\injar>type src\I18n.java
    import java.util.*;
    import java.net.*;
    import java.util.jar.*;
    class I18n {
        public static void main( String ... args ) {
            getLocaleListFromJar();
        }
        private static List<Locale> getLocaleListFromJar() {
            List<Locale> locales = new ArrayList<Locale>();
            try {
                URL packageUrl = I18n.class.getProtectionDomain().getCodeSource().getLocation();
                JarInputStream jar = new JarInputStream(packageUrl.openStream());
                while (true) {
                    JarEntry entry = jar.getNextJarEntry();
                    if (entry == null) {
                        System.out.println( "entry was null ");
                        break;
                    }
                    String name = entry.getName();
                    System.out.println( "found : " +name );
                    /*if (resourceBundlePattern.matcher(name).matches()) {
                        addLocaleFromResourceBundle(name, locales);
                    }*/
               }
            } catch (Exception e) {
                System.err.println(e);
                return null;
                //return getLocaleListFromFile(); // File based implementation in case resources are not in jar
            }
            return locales;
        }
    }
    
    
    C:\java\injar>java -jar i18n.jar
    found : I18n.class
    found : x/
    found : x/y/
    found : x/y/z/
    found : x/y/z/hola.txt
    entry was null