tags:

views:

3328

answers:

5

Hi All

I am trying to read a text file which is set in CLASSPATH system variable. Not a user variable.

I am trying to get input stream to the file as below:

Place the directory of file (D:\myDir)in CLASSPATH and try below:

InputStream in = this.getClass().getClassLoader().getResourceAsStream("SomeTextFile.txt");
InputStream in = this.getClass().getClassLoader().getResourceAsStream("/SomeTextFile.txt");
InputStream in = this.getClass().getClassLoader().getResourceAsStream("//SomeTextFile.txt");

Place full path of file (D:\myDir\SomeTextFile.txt)in CLASSPATH and try the same above 3 lines of code.

But unfortunately NONE of them are working and I am always getting null into my InputStream in.

Any way out please? I googled a lot and none of the websites, including Stack Overflow, has any reliable information about getResourceAsStream().

Regards

Chaitanya

+8  A: 

Please try

InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");

Your tries didn't work because only the class loader for your classes is able to load from the classpath. You used the class loader for the java system itself.

tangens
Not sure about the "/" though. A relative path might work better in this case.
VonC
If you use it without "/" you are looking for your file inside the package of "this".
tangens
InputStream file = this.getClass().getResourceAsStream("SomeTextFile.txt");InputStream file = this.getClass().getResourceAsStream("/SomeTextFile.txt"); InputStream file = this.getClass().getResourceAsStream("//SomeTextFile.txt"); None of the above worked :(
Chaitanya MSV
@Chaitanya: Can you run the example from John Skeet's answer?
Aaron Digulla
A: 

you have to put your 'system variable' on the java classpath.

Salandur
I put System variable itself.
Chaitanya MSV
+13  A: 

With the directory on the classpath, from a class loaded by the same classloader, you should be able to use either of:

// From ClassLoader, all paths are "absolute" already - there's no context
// from which they could be relative. Therefore you don't need a leading slash.
InputStream in = this.getClass().getClassLoader()
                                .getResourceAsStream("SomeTextFile.txt");
// From Class, the path is relative to the package of the class unless
// you include a leading slash, so if you don't want to use the current
// package, include a slash like this:
InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");

If those aren't working, that suggests something else is wrong.

So for example, take this code:

package dummy;

import java.io.*;

public class Test
{
    // This code is nasty and not exception safe. Just demo code!
    public static void main(String[] args) throws Exception
    {
        InputStream stream = Test.class.getResourceAsStream("/SomeTextFile.txt");
        System.out.println(stream != null);
        stream = Test.class.getClassLoader()
            .getResourceAsStream("SomeTextFile.txt");
        System.out.println(stream != null);
    }
}

And this directory structure:

code
    dummy
          Test.class
txt
    SomeTextFile.txt

And then (using the Unix path separator as I'm on a Linux box):

java -classpath code:txt dummy.Test

Results:

true
true
Jon Skeet
You mixed relative and absolute paths up. A path that starts with "/" is absolute (i.e. starts from whatever is listed in CLASSPATH). All other paths are relative to the package of the class on which you call `getResourceAsStream()`
Aaron Digulla
I've fixed your examples and added another one to show how a relative path works.
Aaron Digulla
No, you *broke* my example. I'll edit the comments to make them clearer, but the point is that using ClassLoader all paths are assumed to be absolute already. There's nothing for them to be relative to.
Jon Skeet
Hi Jon Skeet, Thank you very much for your explanation. It worked! and I got what I wanted to know. Thanks again :)RegardsChaitanya
Chaitanya MSV
A: 

When using the Spring Framework (either as a collection of utilities or container - you do not need to use the latter functionality) you can easily use the Resource abstraction.

Resource resource = new ClassPathResource("com/example/Foo.class");

Through the Resource interface you can access the resource as InputStream, URL, URI or File. Changing the resource type to e.g. a file system resource is a simple matter of changing the instance.

yawn
+1  A: 

You say "I am trying to read a text file which is set in CLASSPATH system variable." My guess this is on Windows and you are using this ugly dialog to edit the "System Variables".

Now you run your Java program in the console. And that doesn't work: The console gets a copy of the values of the system variables once when it is started. This means any change in the dialog afterwards doesn't have any effect.

There are these solutions:

  1. Start a new console after every change

  2. Use set CLASSPATH=... in the console to set the copy of the variable in the console and when your code works, paste the last value into the variable dialog.

  3. Put the call to Java into .BAT file and double click it. This will create a new console every time (thus copying the current value of the system variable).

BEWARE: If you also have a User variable CLASSPATH then it will shadow your system variable. That is why it is usually better to put the call to your Java program into a .BAT file and set the classpath in there (using set CLASSPATH=) rather than relying on a global system or user variable.

This also makes sure that you can have more than one Java program working on your computer because they are bound to have different classpaths.

Aaron Digulla