简体   繁体   中英

getResourceAsStream() returns null only when in jar file

I know the same question has been asked many many times, but going through all the answers already posted I couldn't find a solution.

First of all here's the code I'm using to test the issue after i encountered it in my project :

InputStream test;

System.out.println(this.getClass());
System.out.println(("classpath is: " + System.getProperty("java.class.path")));

test = getClass().getResourceAsStream("/pairs/images/100/back/back1.png");

if (test == null)
{
    System.out.println("getClass().getResourceAsStream(\"/pairs/images/100/back/back1.png\") is null");
    test = GridPanel.class.getClassLoader().getResourceAsStream("pairs/images/100/back/back1.png");
}

if (test == null)
{
    System.out.println("GridPanel.class.getClassLoader().getResourceAsStream(\"pairs/images/100/back/back1.png\") is null");
    test = ClassLoader.getSystemClassLoader().getResourceAsStream("pairs/images/100/back/back1.png");
}

if (test == null)
{
    System.out.println("ClassLoader.getSystemClassLoader().getResourceAsStream(\"pairs/images/100/back/back1.png\") is null");
    Thread.currentThread().getContextClassLoader().getResourceAsStream("pairs/images/100/back/back1.png");
}

if (test == null)
    System.out.println("Thread.currentThread().getContextClassLoader().getResourceAsStream(\"pairs/images/100/back/back1.png\") is null");

So as per title everyone of these calls to getResourceAsStream() returns null, but only when executin the jar file, when launching inside the IDE (Netbeans 8.0.2) they all return the correct stream (tested individually not with this piece of code) and I can work with it.

The jar file contents are as follow: http://i.stack.imgur.com/1y8i8.png

While the src folder in the netbeans project folder is the following: http://i.stack.imgur.com/AXj7s.png

So I'm really baffled at the moment, I've tried using the default settings when building with netbeans but I'm losing my head around this issue.

Any hints or ideas would be much appreciated!

I think the getResourceAsStream is not reading from filesystem, the leading slash will try to read from the root of the classpath (if you add a directory will read from the root). If you don't put the leading slash, you will read from the package the class is from.

Did you add the directory/subdirectories you want to read the file from in the classpath?

TL;DR It was due some stupid issue with NTFS permission, moving the jar made it work

So I feel very stupid right now...

I tried running it in a Linux environment and everything worked as supposed. Each one of those calls was returning a non-null InputStream pointing to the resource.

So I did something very simple: just moved around the compiled jar in Windows to check if it had something to do with NTFS permissions (keep in mind that I'm using an administrator account and I can freely write, read and execute in those folders). Moving it to the root of the project didn't work, but moving it on the desktop WORKED.

What amazes me more is that in some other parts of the projects I'm doing

URL jarUrl = PairsDeck.class.getProtectionDomain().getCodeSource().getLocation();

to read the whole content of the jar file and that works every time even in the old directory, so that's why I hadn't thought of screwed permissions since the beginning (and I was launching it from a command prompt with admin privileges).

So I guess somehow the program can read its jar with that call but not load resources from it inside my netbeans project folder due to some issues with NTFS permissions.

To add some confusion

File file = new File(jarUrl.toURI());
file.canWrite();
file.canRead();
file.canExecute(); 

all of the above return true.

I'm just curious to know if there was a way to understand better the issue and maybe have a way to signal some permissions error from the java code.

Thanks wholeheartedly to everybody involved for the help!

There are two problems here.

  1. Windows is case-insensitive. Other platforms and inside a jar names are case-sensitive.

  2. The getClass() class determines in which jar/class path the resource is souught. Especially a unit test will not be put in a jar, or a child class might be located outside the jar. Either use a SomeClassInJar.class or use a ClassLoader which searches over all jars/class paths. A class loader uses only absolute paths, and you must not start the path with a / .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM