Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading files with ClassLoader

This problem has been bugging me for a while. I have to load a couple files in my java app, and the only way I got working so far looks like this:

URL hsURL;
if(System.getProperty("os.name").toLowerCase().contains("windows")) {
    hsURL = new URL("file:/" + System.getProperty("user.dir") + "/helpsets/helpset.hs");
}
else {
    hsURL = new URL("file://" + System.getProperty("user.dir") + "/helpsets/helpset.hs");
}

But this is ugly and terrible. For a while I thought I had this working:

hsURL = ClassLoader.getSystemResource("helpsets/helpset.hs");

But that no longer works for some reason (I must have changed something and not noticed. It returns null.

Should I be using getResource() instead of getSystemResource() (if so, why is getSystemResource() static but not getResource())?

I am using eclipse and I have tried including the folder in the build path (classpath) and not including it, it doesn't seem to make a difference.

like image 823
twolfe18 Avatar asked Jul 13 '09 14:07

twolfe18


People also ask

How do I load a file using ClassLoader?

In the above code snippet, we used the current class to load a file using getResourceAsStream method and passed the absolute path of the file to load. The same method is available on a ClassLoader instance as well: ClassLoader classLoader = getClass(). getClassLoader(); InputStream inputStream = classLoader.

Which ClassLoader loads JAR files from JDK?

The Bootstrap class loader loads the basic runtime classes provided by the JVM, plus any classes from JAR files present in the system extensions directory. It is parent to the System class loader. To add JAR files to the system extensions, directory, see Using the Java Optional Package Mechanism.

Is it possible to load a class by two ClassLoader?

A class is always identified using its fully qualified name (package. classname). So when a class is loaded into JVM, you have an entry as (package, classname, classloader). Therefore the same class can be loaded twice by two different ClassLoader instances.

Which ClassLoader is used to load a class?

Java ClassLoader is used to load the classes at run time. In other words, JVM performs the linking process at runtime. Classes are loaded into the JVM according to need. If a loaded class depends on another class, that class is loaded as well.


2 Answers

getSystemResource is static because it will use the system classloader, which is available statically. (ClassLoader.getSystemClassLoader)

If your resource is available in the classpath, I would suggest using ClassLoader.getResource() or Class.getResource from an appropriate class, e.g.

Foo.class.getResource("/helpsets/helpset.hs");

(ClassLoader.getResource is "absolute"; Class.getResource is relative to the package of the class unless you prefix it with a '/'.)

If this doesn't work, please post how your app is configured in terms of the classpath, and where your file is.

EDIT: I usually find the URL less useful than an InputStream, so I use getResourceAsStream instead of getResource. YMMV

like image 157
Jon Skeet Avatar answered Sep 23 '22 22:09

Jon Skeet


You've mentioned several different things here, so let's sort them out.

1) Creating a "file:" URL based on "user.dir"

The "user.dir" property refers to the current working directory -- wherever the user might have been when s/he started the app. Chances are good that files written here will disappear between two runs (because the user might run from a different directory).

The "user.home" property refers to the user's home directory -- which should remain the same between runs.

In either case, use a File object to open files, don't muck around with creating a "file:" URL. You get no benefit, and as you can see, you have to write messy code to access it.

2) Retrieving a resource via the classloader

This is meant to retrieve files that are packaged with your application -- read-only files. As you have seen, there are multiple variants. I prefer using the following, because I assume that a class will want to load a file that's packaged with it.

InputStream in = this.getClass().getClassLoader().getResourceAsStream(fileName);
like image 43
kdgregory Avatar answered Sep 25 '22 22:09

kdgregory