getResourceAsStream returns null

JavaFile IoResources

Java Problem Overview


I'm loading a text file from within a package in a compiled JAR of my Java project. The relevant directory structure is as follows:

/src/initialization/Lifepaths.txt

My code loads a file by calling Class::getResourceAsStream to return a InputStream.

public class Lifepaths {
    public static void execute() {
        System.out.println(Lifepaths.class.getClass().
            getResourceAsStream("/initialization/Lifepaths.txt"));
    }

    private Lifepaths() {}

    //This is temporary; will eventually be called from outside
    public static void main(String[] args) {execute();}
}

The print out will always print null, no matter what I use. I'm not sure why the above wouldn't work, so I've also tried:

  • "/src/initialization/Lifepaths.txt"
  • "initialization/Lifepaths.txt"
  • "Lifepaths.txt"

Neither of these work. I've read numerous questions so far on the topic, but none of them have been helpful - usually, they just say to load files using the root path, which I'm already doing. That, or just load the file from the current directory (just load filename), which I've also tried. The file is being compiled into the JAR in the appropriate location with the appropriate name.

How do I solve this?

Java Solutions


Solution 1 - Java

Lifepaths.class.getClass().getResourceAsStream(...) loads resources using system class loader, it obviously fails because it does not see your JARs

Lifepaths.class.getResourceAsStream(...) loads resources using the same class loader that loaded Lifepaths class and it should have access to resources in your JARs

Solution 2 - Java

The rules are as follows:

  1. check the location of the file you want to load inside the JAR (and thus also make sure it actually added to the JAR)
  2. use either an absolute path: path starts at the root of the JAR
  3. use an relative path: path starts at the package directory of the class you're calling getResource/ getResoucreAsStream

And try:

Lifepaths.class.getResourceAsStream("/initialization/Lifepaths.txt")

instead of

Lifepaths.class.getClass().getResourceAsStream("/initialization/Lifepaths.txt")

(not sure if it makes a difference, but the former will use the correct ClassLoader/ JAR, while I'm not sure with the latter)

Solution 3 - Java

So there are several ways to get a resource from a jar and each has slightly different syntax where the path needs to be specified differently.

The best explanation I have seen is this article from InfoWorld. I'll summarize here, but if you want to know more you should check out the article.

Methods

  1. ClassLoader.getResourceAsStream().

Format: "/"-separated names; no leading "/" (all names are absolute).

Example: this.getClass().getClassLoader().getResourceAsStream("some/pkg/resource.properties");

  1. Class.getResourceAsStream()

Format: "/"-separated names; leading "/" indicates absolute names; all other names are relative to the class's package

Example: this.getClass().getResourceAsStream("/some/pkg/resource.properties");

Updated Sep 2020: Changed article link. Original article was from Javaworld, it is now hosted on InfoWorld (and has many more ads)

Solution 4 - Java

Don't use absolute paths, make them relative to the 'resources' directory in your project. Quick and dirty code that displays the contents of MyTest.txt from the directory 'resources'.

@Test
public void testDefaultResource() {
    // can we see default resources
    BufferedInputStream result = (BufferedInputStream) 
         Config.class.getClassLoader().getResourceAsStream("MyTest.txt");
    byte [] b = new byte[256];
    int val = 0;
    String txt = null;
    do {
        try {
            val = result.read(b);
            if (val > 0) {
                txt += new String(b, 0, val);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } 
    } while (val > -1);
    System.out.println(txt);
}

Solution 5 - Java

You might want to try this to get the stream i.e first get the url and then open it as stream.

URL url = getClass().getResource("/initialization/Lifepaths.txt"); 
InputStream strm = url.openStream(); 

I once had a similar question: https://stackoverflow.com/questions/16563622/reading-txt-file-from-jar-fails-but-reading-image-works/16564611#16564611

Solution 6 - Java

I found myself in a similar issue. Since I am using maven I needed to update my pom.xml to include something like this:

   ...
</dependencies>
<build>
	<resources>
		<resource>
			<directory>/src/main/resources</directory>
		</resource>
		<resource>
			<directory>../src/main/resources</directory>
		</resource>
	</resources>
	<pluginManagement>
        ...

Note the resource tag in there to specify where that folder is. If you have nested projects (like I do) then you might want to get resources from other areas instead of just in the module you are working in. This helps reduce keeping the same file in each repo if you are using similar config data

Solution 7 - Java

There seems to be issue with the ClassLoader that you are using. Use the contextClassLoader to load class. This is irrespective of whether it is in a static/non-static method

Thread.currentThread().getContextClassLoader().getResourceAsStream......

Solution 8 - Java

Roughly speaking:

getClass().getResource("/") ~= Thread.currentThread().getContextClassLoader().getResource(".")

Suppose your project structure is like the following:

├── src
│   ├── main
│   └── test
│       ├── java
│       │   └── com
│       │       └── github
│       │           └── xyz
│       │               └── proj
│       │                   ├── MainTest.java
│       │                   └── TestBase.java
│       └── resources
│           └── abcd.txt
└── target
    └── test-classes  <-- this.getClass.getResource("/")
        │              `--Thread.currentThread().getContextClassLoader().getResources(".")
        ├── com
        │   └── github
        │       └── xyz
        │           └── proj  <-- this.getClass.getResource(".")
        │               ├── MainTest.class
        │               └── TestBase.class
        └── resources
            └── abcd.txt

// in MainTest.java
this.getClass.getResource("/") -> "~/proj_dir/target/test-classes/"
this.getClass.getResource(".") -> "~/proj_dir/target/test-classes/com/github/xyz/proj/"
Thread.currentThread().getContextClassLoader().getResources(".") -> "~/proj_dir/target/test-classes/"
Thread.currentThread().getContextClassLoader().getResources("/") ->  null

Solution 9 - Java

The default JVM classloader will use parent-classloader to load resources first: deletegate-parent-classloader.

Lifepaths.class.getClass()'s classloader is bootstrap classloader, so getResourceAsStream will search $JAVA_HOME only, regardless of user provided classpath. Obviously, Lifepaths.txt is not there.

Lifepaths.class 's classloader is system classpath classloader, so getResourceAsStream will search user-defined classpath and Lifepaths.txt is there.

When using java.lang.Class#getResourceAsStream(String name), a name which doesn't start with '/' will be added with package name as a prefix. To avoid this use java.lang.ClassLoader#getResourceAsStream instead.

For example:

ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourceName = "Lifepaths.txt";
InputStream resourceStream = loader.getResourceAsStream(resourceName); 

Solution 10 - Java

What worked for me was to add the file under My Project/Java Resources/src and then use

this.getClass().getClassLoader().getResourceAsStream("myfile.txt");

I didn't need to explicitly add this file to the path (adding it to /src does that apparently)

Solution 11 - Java

Don't know if of help, but in my case I had my resource in the /src/ folder and was getting this error. I then moved the picture to the bin folder and it fixed the issue.

Solution 12 - Java

Make sure your resource directory (e.g. "src") is in your classpath (make sure it's a source directory in your build path in eclipse).

Make sure clazz is loaded from the main classloader.

Then, to load src/initialization/Lifepaths.txt, use

clazz.getResourceAsStream("/initialization/Lifepaths.txt");

Why: clazz.getResourcesAsStream(foo) looks up foo from within the classpath of clazz, relative to the directory clazz lives in. The leading "/" makes it load from the root of any directory in the classpath of clazz.

Unless you're in a container of some kind, like Tomcat, or are doing something with ClassLoaders directly, you can just treat your eclipse/command line classpath as the only classloader classpath.

Solution 13 - Java

if you are using Maven make sure your packing is 'jar' not 'pom'.

<packaging>jar</packaging>

Solution 14 - Java

What you really need is a full absolute classPath for the file. So instead of guessing it, try to find out the ROOT and then move the file to a better location base one <.war> file structures...

URL test1 = getClass().getResource("/");
URL test2 = getClass().getClassLoader().getResource("/");            
URL test3 = getClass().getClassLoader().getResource("../");

logger.info(test1.getPath()); 
logger.info(test2.getPath());
logger.info(test3.getPath());

Solution 15 - Java

What worked for me is I placed the file under

src/main/java/myfile.log

and

InputStream is = getClass().getClassLoader().getResourceAsStream("myfile.log");
		
		if (is == null) {
			throw new FileNotFoundException("Log file not provided");
		}

Solution 16 - Java

> jdk >=9 需要在module-info模块中把非根目录/非共父目录的包给它open了。

jdk >=9 need open resource dir in module-info.java , such as :

  • src
    • java
    • resoureces
      • conf
        • config.json
      • log4j2.xml
      • openapi.yaml

If you need read conf/config.json , you need two step :

// in module-info.java
module your.mod.name {
    open conf;
}

// then in java code
getClassLoader().getResourceAsStream("conf/config.json");

Else if you need read other in root , it's only :

getClassLoader().getResourceAsStream("openapi.yaml");

> you can see {@link java.lang.ClassLoader#getResourceAsStream(String)} known why ~

Solution 17 - Java

Please remove

../src/main/resources

or include file you are trying to read

Solution 18 - Java

In pom.xml manage or remove ../src/main/resources

Solution 19 - Java

My caller class was in src/main/...

What helped me to load resource from src/test/resources/folder/file.properties

`properties.load(getClass().getClassLoader().getResourceAsStream("folder/file.properties"));`

https://howtodoinjava.com/java/io/read-file-from-resources-folder/

Java 11

Solution 20 - Java

While not intended to be an answer, I'm presenting this suggestion as an answer so I can get the screenshot in.

For those of you developing on a Windows platform, I highly recommend the Microsoft utility ProcMon, or Process Monitor.

Process Monitor is one utility in a suite of utilities Microsoft gives away (you don't even need to be signed in to download). They are all available at sysinternals.com, the original host that Microsoft acquired and just kept.

Process Monitor can monitor a ton of events that are associated with any running process. If you specify the File Open event and provide the file name (or part of the file name), it will log which process attempted to open the file and it will show every directory searched. This can be useful when you don't know where your running code is looking for the file you specified in your source/config. Here's an example:

enter image description here

Here I'm looking for (and not finding) a schema file (XSD) so that the code can use it to validate some user supplied XML.

Solution 21 - Java

If you are using IDEA, make sure to mark your resources folder as 'Resources' so that the path can be recognized by IDE correctly.

Let's say you have a file named 'book.json' in 'resources/', then to use the resources in it, you can do it like this

InputStream input = Main.class.getResourceAsStream("/book.json");

enter image description here

Solution 22 - Java

@Emracool... I'd suggest you an alternative. Since you seem to be trying to load a *.txt file. Better to use FileInputStream() rather then this annoying getClass().getClassLoader().getResourceAsStream() or getClass().getResourceAsStream(). At least your code will execute properly.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1131435View Question on Stackoverflow
Solution 1 - JavahoazView Answer on Stackoverflow
Solution 2 - JavaPuceView Answer on Stackoverflow
Solution 3 - JavagreedybuddhaView Answer on Stackoverflow
Solution 4 - JavaPaul SmithView Answer on Stackoverflow
Solution 5 - JavaMrDView Answer on Stackoverflow
Solution 6 - JavaploscoView Answer on Stackoverflow
Solution 7 - JavaBinita BharatiView Answer on Stackoverflow
Solution 8 - JavaShijing LvView Answer on Stackoverflow
Solution 9 - JavaridoxView Answer on Stackoverflow
Solution 10 - JavaCommonCoreTawanView Answer on Stackoverflow
Solution 11 - JavaLeo UfimtsevView Answer on Stackoverflow
Solution 12 - JavaBobby MartinView Answer on Stackoverflow
Solution 13 - JavaFeku279View Answer on Stackoverflow
Solution 14 - JavaConAimView Answer on Stackoverflow
Solution 15 - JavaAkash YellappaView Answer on Stackoverflow
Solution 16 - JavatcsnzhView Answer on Stackoverflow
Solution 17 - JavaShahid Hussain AbbasiView Answer on Stackoverflow
Solution 18 - JavaShahid Hussain AbbasiView Answer on Stackoverflow
Solution 19 - JavaqwebekView Answer on Stackoverflow
Solution 20 - JavambmastView Answer on Stackoverflow
Solution 21 - Javaj5shiView Answer on Stackoverflow
Solution 22 - JavaJainView Answer on Stackoverflow