5

I have something like the following project structure

-project 
    -src/main/java // source folder
        -com.mypackage
            -Utility.java
            -some.properties
    -src/main/resources // source folder
        -configuration_files
            -configuration_report.txt

I'm generating the jar with Eclipse's Export function. The above translates to a jar with the structure:

-myjar.jar
    -com
        -mypackage
            -Utility.class
            -some.properties
    -configuration_files
        -configuration_report.txt

Within the Utility class, I'm trying to get the InputStream from configuration_report.txt.

I was doing this (it's within a static method):

Utility.class.getResourceAsStream("/configuration_files/configuration_report.txt"); 

which seems to be validated by the answer to this question, since the file is not in the same package as the class requesting it.

When I run it, however, it returns null. Why?

Note that for the some.properties file, I could do both

Utility.class.getResourceAsStream("/com/package/some.properties");
Utility.class.getResourceAsStream("some.properties");

and I would get the stream.

I'm running this from the command line if it makes any difference.

java [-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=1044] -cp myjar.jar MyMain

If I try to run it within Eclipse, it works...

Edit:

This code is relevant. With or without the preceding /, it return null

    String sourceFilePath = "/configuration_files" + File.separator + "configuration_report.txt";
    InputStream in = Utility.class.getResourceAsStream(sourceFilePath);
4

1 回答 1

9

After many tries, the solution comes down to this little javadoc entry for ClassLoader#getResource(String):

The name of a resource is a '/'-separated path name that identifies the resource.

The snippet I had originally posted would've worked

Utility.class.getResourceAsStream("/configuration_files/configuration_report.txt"); 

but I wasn't using /, I was using File.separator like in my edit:

String sourceFilePath = "/configuration_files" + File.separator + "configuration_report.txt";

thinking the class loader worked like OS specific File operations. The first / was matched, but the File.separator evaluated to \\ since I'm on Windows.

The javadoc for Class#getResource(String) says more of the same.

Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').

As to why this worked on Eclipse, but not from the command line, I'm still unsure, but look at @andy's comment below.

This article gives is a good explanation of this situation.

于 2013-05-01T16:17:50.380 回答