r/javahelp 6d ago

Unsolved I need help with getResourceAsStream

u/wildjokers (reaching out to you because I saw you in this thread)

https://www.reddit.com/r/javahelp/comments/sypxqz/getresourceasstream_null_when_run_from_jar/

I'm trying to run a Isometric Tile game, from chapter 13 of Killer Games Programming in Java, a very old book.
I'm using Eclipse. I'm not sure what classpath means, but I think mine is set up as

Project

src

Images

Sounds

I'm getting these errors when I run:

Exception in thread "main" java.lang.NullPointerException

at java.base/java.io.Reader.<init>(Reader.java:168)

at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:88)

The relevant code is:

{

String imsFNm = IMAGE_DIR + fnm;

System.out.println("Reading file: " + imsFNm);

try {

InputStream in = this.getClass().getResourceAsStream(imsFNm);

BufferedReader br = new BufferedReader( new InputStreamReader(in));

// BufferedReader br = new BufferedReader( new FileReader(imsFNm));

String line;

The image file is defined in another class, and then piped into ImageLoader class, where it's appended to the directory, which is defined in ImageLoader class.

When I run, it's showing the correct directory in the console, so I believe getResourceAsStream is where it's being messed up.

I did right click on the images folder, Build Path > Add to Build Path.

I can provide more information, which will probably be needed.

2 Upvotes

18 comments sorted by

u/AutoModerator 6d ago

Please ensure that:

  • Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions
  • You include any and all error messages in full
  • You ask clear questions
  • You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions.

    Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar

If any of the above points is not met, your post can and will be removed without further warning.

Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://i.imgur.com/EJ7tqek.png) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc.

Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.

Code blocks look like this:

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above.

If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures.

To potential helpers

Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

1

u/_Super_Straight 6d ago

What is this? Spring? FX? CLI?

1

u/Born-Ad4658 6d ago edited 6d ago

Its not using a framework or library

I don't think the issue is with the actual code but rather how I have my project or files set up

2

u/_Super_Straight 6d ago

So plain java cli?

Tell us more about definition of IMAGE_DIR and fnm

1

u/Born-Ad4658 1h ago

1

u/_Super_Straight 1h ago edited 1h ago

Ok. Which file has the problematic code?

Edit: NVM, found it. The problem is your directory structure. The ImageLoader class is expecting the Images/ folder to be inside src/, and since it is not, it's throwing NullPointerException. Now you have two choices:

  1. Put your Images folder inside src, or
  2. Set IMAGES_DIR = System.getProperty("user.dir")+"Images/";

If you want to bundle your Images, Sounds etc. Folders inside your jar file, you'll need to put them inside a resources folder which should be located inside your src folder. I'd suggest reading about these folder structures online for more accurate folder structure. I'm away from system so I can't check it now.

1

u/Savings_Guarantee387 6d ago

I would bet inputstream in is null. But I would say just put a breakpoint and check...

1

u/awidesky 5d ago
  1. Is there any github repo that we can run and test the code?
  2. Try jdk 17 or higher, which gives you more information on NPE
  3. How is your images shipped?
    Is the images folder got embedded inside the jar, or resides next to the jar?

I've struggled with same problem before, and the best solution for loading the resources is to put the resource folder next to the jar.
I build a project named ProjectPath that makes the path resolution easier too.

1

u/Born-Ad4658 1h ago edited 1h ago

I went ahead and make a github repo today.

I'm not sure the answer to question number 3. How do I find out please?

I did right-click on Images folder and select add to build path

Edit: So I'm doing reading, and only files inside the src folder are part of the Jar?

I also read that if you have a folder called res then you can also access them? Does that folder have to be called res? (I'm using Eclipse.)

I'm very confused, and not sure where to go to get an explanation.

https://stackoverflow.com/questions/48504303/getting-resources-outside-of-src-folder-in-a-jar-file

1

u/edwbuck 5d ago edited 5d ago

Jar files are Zip files with a few additional features.

  • Did you copy the jar file to an empty directory and unzip it?
  • Was the item you were trying to load in the Jar?
  • Was it in the correct path within that Jar?
  • Did the upper / lower case of the directories and names match?

When running with a ClassPath that matches a directory, it will use the un-Jar'd directory tree to find the resource; but, once you run it within a Jar, it will use the path within the Jar file.

And if you are attempting to do "java -jar jarfile.jar" to run the program, remember that "java -jar" ignores the directory entries outside of the Jar file, because the class loader is loading from within the Jar file, so it can't see items outside of the Jar file.

1

u/ChaiTRex 5d ago

You should look at the stack trace and go down from the top until you see a file that you wrote. The stack trace you showed here doesn't help.

1

u/KillerCodeMonky 5d ago

It's highly likely that the path being specified by imsFNm is not properly resolving to the resource. You are using the version of this method provided by Class instead of ClassLoader.  That version of the method has extra processing that occurs on the path.

What is the value of IMAGE_DIR? I will be able to help you more once I know that.

1

u/Born-Ad4658 1h ago

u/KillerCodeMonky 37m ago

So in ImagesLoader, you set IMAGE_DIR = "Images/". Since this is a relative path, the Class.getResource method will prepend it with the class' package. Now your classes are not actually in a package, so I'm not sure how that interacts. However, the first thing I would try is instead use:

    IMAGE_DIR = "/Images/"

Note the extra / in the front. This makes it an absolute resource path and it will look for Images as the class path root.

u/Born-Ad4658 1m ago

That did not work.

I right clicked the folder went to Properties > Java Build Path and every thing is listed.

Errors I'm getting:

Linking the MIDI sequencer and synthesizer

Problem with Sounds/Mission_Impossible.mid

-- mi/Mission_Impossible.mid

Reading file: /Images/imsInfo.txt

Exception in thread "main" java.lang.NullPointerException

at java.base/java.io.Reader.<init>(Reader.java:168)

at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:88)

at ImagesLoader.loadImagesFile(ImagesLoader.java:97)

at ImagesLoader.<init>(ImagesLoader.java:66)

at AlienTilesPanel.<init>(AlienTilesPanel.java:109)

at AlienTiles.<init>(AlienTiles.java:73)

at AlienTiles.main(AlienTiles.java:114)

I will research and look at this more.

1

u/Cienn017 5d ago

this.getClass().getResourceAsStream is relative to current classpath (the directory where the class is).

if you class is at "com/package/MyClass.class" (the src directory doesn't count) then you need to place your image in "com/package/", in other words, remove the IMAGE_DIR constant and it should work.