views:

3152

answers:

5

Is there a way in Java to construct a File instance on a resource retrieved from a jar through the classloader?

My application uses some files from the jar (default) or from a filesystem directory specified at runtime (user input). I'm looking for a consistent way of
a) loading these files as a stream
b) listing the files in the user-defined directory or the directory in the jar respectively

Edit: Apparently, the ideal approach would be to stay away from java.io.File altogether. Is there a way to load a directory from the classpath and list its contents (files/entities contained in it)?

+3  A: 

Try this:

ClassLoader.getResourceAsStream ("some/pkg/resource.properties");

There are more methods available, e.g. see here: http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html

grigory
Thanks for your response. I know about getResourceAsStream, but I don't think I can load a directory from the classpath through that.
Mantrum
In Java directory is a file (UNIX roots I guess) so you should at least try.
grigory
I think to list files in a directory you are going to need to use java.io.File. You can look up files with the ClassLoader.findResource which returns a URL that can be passed to File.
Nathan Voxland
+5  A: 

ClassLoader.getResourceAsStream and Class.getResourceAsStream are definitely the way to go for loading the resource data. However, I don't believe there's any way of "listing" the contents of an element of the classpath.

In some cases this may be simply impossible - for instance, a ClassLoader could generate data on the fly, based on what resource name it's asked for. If you look at the ClassLoader API (which is basically what the classpath mechanism works through) you'll see there isn't anything to do what you want.

If you know you've actually got a jar file, you could load that with ZipInputStream to find out what's available. It will mean you'll have different code for directories and jar files though.

One alternative, if the files are created separately first, is to include a sort of manifest file containing the list of available resources. Bundle that in the jar file or include it in the file system as a file, and load it before offering the user a choice of resources.

Jon Skeet
I agree it's annoying - but it makes ClassLoader more widely applicable in other ways. For instance, it's easy to write a "web classloader" because the web is good for fetching files, but it doesn't typically *list* files.
Jon Skeet
+3  A: 

I had the same problem and was able to use the following:

// Load the directory as a resource
URL dir_url = ClassLoader.getSystemResource(dir_path);
// Turn the resource into a File object
File dir = new File(dir_url.toURI());
// List the directory
String files = dir.list()
Chris Conway
+1  A: 

This is one option: http://www.uofr.net/~greg/java/get-resource-listing.html

Fish
A: 
 public static String getResourceDir() {
        String resourceDir = "resources/test/";
        try {
            if (!(new File(resourceDir)).isDirectory())
                throw new Exception();
        } catch (Exception e) {
            resourceDir = "test/";
            try {
                if (!(new File(resourceDir)).isDirectory())
                    throw new Exception();
            } catch (Exception f) {
                resourceDir = "";
            }
        }
        return resourceDir;
Kate Khapatko