14

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.

Donato Szilagyi
  • 4,279
  • 4
  • 36
  • 53
twolfe18
  • 2,228
  • 4
  • 24
  • 25

2 Answers2

29

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

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • If you are only interested in the contents, you're probably better off using getResourceAsStream() on the ClassLoader – Rich Seller Jul 13 '09 at 14:34
  • well, i haven't gotten this working yet. i am trying to load a file that is in a different package as the class i am loading it from, so i need some kind of absolute reference. – twolfe18 Jul 13 '09 at 14:36
  • 2
    @twolfe18: Yes, so use "/helpsets/helpset.hs" as shown in the answer. @Rich: Yes, will edit to mention that. – Jon Skeet Jul 13 '09 at 14:50
  • in the project folder there is the source package and the helpsets package. the source package is set up like: src/foo/bar/my_class – twolfe18 Jul 13 '09 at 15:05
  • Unless the helpsets package is set up to be included in the output (e.g. by making it a source path) then it won't be present in the bin directory (or wherever you're putting the output) so you won't be able to get at it. – Jon Skeet Jul 13 '09 at 15:20
4

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);
kdgregory
  • 38,754
  • 10
  • 77
  • 102