Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read directory inside JAR with InputStreamReader

So, this question has been asked a million times i believed and I've been reading them for a couple of hours and trying several options given by some people but none of them work for me.

I want to list all the files inside a directory inside the application's JAR, so in IDE this works:

File f = new File(this.getClass().getResource("/resources/").getPath());

for(String s : f.list){
   System.out.println(s);
}

That gives me all the files inside the directory.

Now, i've tried this also:

InputStream in = this.getClass().getClassLoader().getResourceAsStream("resources/");
    InputStreamReader inReader = new InputStreamReader(in);
    Scanner scan = new Scanner(inReader);

    while (scan.hasNext()) {
        String s = scan.next();
        System.out.println("read: " + s);
    }

    System.out.println("END OF LINE");

And from IDE it prints ALL the files in the directory. Outside IDE prints: "END OF LINE".

Now, I can find an entry inside a Jar with this too:

        String s = new File(this.getClass().getResource("").getPath()).getParent().replaceAll("(!|file:\\\\)", "");
        JarFile jar = new JarFile(s);

            JarEntry entry = jar.getJarEntry("resources");

        if (entry != null){
            System.out.println("EXISTS");
            System.out.println(entry.getSize());
        }

That's some horrible coding i had to do to that String.

Anyway... I can't get the list of resources inside the "resources" directory within the Jar... How can I do this???

like image 434
Jh62 Avatar asked Aug 15 '13 06:08

Jh62


People also ask

How can I access a folder inside of a resource folder from inside my JAR file?

What you could do is to use getResourceAsStream() method with the directory path, and the input Stream will have all the files name from that dir. After that you can concat the dir path with each file name and call getResourceAsStream for each file in a loop.

How do I get a list of files in a JAR file?

Given an actual JAR file, you can list the contents using JarFile. entries() . You will need to know the location of the JAR file though - you can't just ask the classloader to list everything it could get at. You should be able to work out the location of the JAR file based on the URL returned from ThisClassName.


2 Answers

There's no way to simply get a filtered list of internal resources without first enumerating over the contents of the Jar file.

Luckily, that's actually not that hard (and luckily for me you've done most of the hardwork).

Basically, once you have a reference to the JarFile, you simple need to ask for its' entries and iterate over that list.

By checking the JarEntry name for the required match (ie resources), you can filter the elements you want...

For example...

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ReadMyResources {

    public static void main(String[] args) {
        new ReadMyResources();
    }

    public ReadMyResources() {
        JarFile jf = null;
        try {            
            String s = new File(this.getClass().getResource("").getPath()).getParent().replaceAll("(!|file:\\\\)", "");
            jf = new JarFile(s);

            Enumeration<JarEntry> entries = jf.entries();
            while (entries.hasMoreElements()) {
                JarEntry je = entries.nextElement();
                if (je.getName().startsWith("resources")) {
                    System.out.println(je.getName());
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                jf.close();
            } catch (Exception e) {
            }
        }
    }

}

Caveat

This type of question actually gets ask a bit. Rather then trying to read the contents of the Jar at runtime, it would be better to produce some kind of text file which contained a list of the available resources.

This could be produced by your build process dynamically before the Jar file is created. It would be a much simpler solution to then read this file in (via getClass().getResource(), for example) and then look up each resource list in the text file...IMHO

like image 122
MadProgrammer Avatar answered Nov 14 '22 05:11

MadProgrammer


For Spring Framework users, have a look at PathMatchingResourcePatternResolver to do something like the following:

PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:path/to/resource/*.*");

for (Resource resource : resources) {
    InputStream inStream = resource.getInputStream();
    // Do something with the input stream
}
like image 8
solimant Avatar answered Nov 14 '22 05:11

solimant