views:

3319

answers:

6

This is mind-boggling... I can make getResource() and getResourceAsStream() work properly when I run Java on my packaged JAR file that includes a text file. (for reference see the Sun docs on accessing resources) I can't seem to make the same program work properly when I am running it within Eclipse, even though I've placed my text file in the same tree as my compiled .class files

Can one of you point me at any subtleties to ensure that getResource() and getResourceAsStream() functions work properly?

I have a hunch it has to do with CLASSPATH and/or where Eclipse puts the .class files it autocompiles. (I've noticed when I run Ant, it compiles all the Java files that have changed since my last Ant build, even though Eclipse has compiled those Java files already.)

+6  A: 

If you put your text file along with your source files, Eclipse will copy it to wherever it's placing its compiled .class files, and so you'll see your text file when you run your app from Eclipse (and you will be able to edit the file from within Eclipse as well).

Chochos
Also make sure Eclipse knows about the files: "Refresh" the source tree if they were added outside of Eclipse. (As noted by Jason S in another answer.)
David Leppik
+1  A: 

I have a hunch it has to do with CLASSPATH and/or where Eclipse puts the .class files it autocompiles.

In the Run Configuration for however you are launching your application, go to the Classpath tab and add the root folder of the path that you are using to access the file.

So for example if you are trying to load "blah/file.txt" and the file resides in "folder/blah/file.txt", add "folder" to the classpath. If you are trying to load the resource with just "file.txt", then add "folder/blah".

matt b
A: 

What precisely do you mean by "work properly"? What's the error/behaviour?

I suggest using getResource to find the URL of one of your .class files (or roughly equivalently getClass().getProtectionDomain().getCodeSource(). You may find that it is pointing somewhere unexpected.

Tom Hawtin - tackline
+5  A: 

A few notes:

First -- as Chocos says, put it in the eclipse source dirs, not the binary dirs. Eclipse will clear the binary dirs when you "clean", as well as clean up unmatched files. It will copy non-java source files to the binary dir.

This means that even though you drop the file in the binary dir, it may be deleted by eclipse...

Keep in mind that getResourceAsStream and getResource operate relative to the package of the code that calls them. For example:

package a.b.c;
public class Foo {
   ...
   getClass().getClassLoader().getResourceAsStream("fee.txt");
   ...
}

This will actually look for a/b/c/fee.txt; the package is pre-pended. This works well if you have the fee.txt in the same source dir as the Foo.java file, or if you have a separate set of resource dirs on the classpath with the same directory structure.

If you use

...getResourceAsStream("/fee.txt");

it will look for fee.txt directly on the classpath.

When you run from the command-line, where in the JAR is the resource file? -- Scott

Scott Stanchfield
+2  A: 

Found the problem!

I did have my image files in the source tree. (in my Ant build, I copy them to the build dir)

The problem was that I had not done a recent refresh of the source tree in Eclipse. So the files were there but Eclipse wasn't paying any attention to them.

Thanks for clueing me in to the fact that Eclipse should have them in my source tree.

Jason S
If you go to Window->Preferences->General->Workspace, check the "Refresh Automatically" box -- that'll prevent that issue in the future. Otherwise, make sure you add things to the project through eclipse (you can File->Import and on some platforms just drag/drop items into the project)
Scott Stanchfield
+1  A: 

I had the same problem in with IntelliJ, the solution for that was, In project settings, add the folder with the resource files, in my case sound files, as source. Add ?*.wav (or your pref filetype) in Settings->Compiler Resource patterns.

BJF