Having an issue loading text files

I’m currently having an issue where my files will load fine with eclipse, however, they won’t load when the jar is exported and run. Here is the code that is giving me trouble.


	private static void loadFirstNamesMale(){
		try{
			URL url = (Assets.class.getResource("/firstNamesMale.src")); // This is apparently returning as null.
			BufferedReader reader = new BufferedReader(new FileReader(new File(url.getFile())));
			String line = "";
			while((line = reader.readLine()) != null){
				firstNameMale.add(line);
			}
			System.out.println("Loaded: firstNamesMale.src");
		}catch(Exception e){
			e.printStackTrace();
		}
	}

I can’t seem to find the problem. Any help is appreciated.

In Eclipse, I recommend not to use class folders. They can have export issues when improperly configured. The easy way is to use a [icode]package[/icode]

  • First make a package called [icode]res[/icode]
  • Then drag all your resources from explorer to the package.
  • Now you can use this code to get an [icode]InputStream[/icode]

public InputStream getInputStream(String name)
{
    return getClass().getClassLoader().getResourceAsStream("res/" + name);
}

This simply works. Make sure you call it with only the file name but not the resource folder.

Yup: Found the error in your code. The error doesn’t lies at getting the URL but is at using a [icode]FileReader[/icode]

Notice that you can’t use [icode]File[/icode] to represent resources which are packed in JAR files. Hence your call to [icode]url.getFile()[/icode] returns [icode]null[/icode]

Change your code to


private static void loadFirstNamesMale()
{
    try
    {
@@        InputStream stream = Assets.class.getResourceAsStream("/firstNamesMale.src");
@@        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        String line = "";
        while ((line = reader.readLine()) != null)
        {
            firstNameMale.add(line);
        }
        System.out.println("Loaded: firstNamesMale.src");
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

Hope this helps. I still recommend to use packages to load files easily.

I did as you said in your first post and moved everything over into a package and setup the input stream getter, however, I’m still getting a null pointer when I create the BufferedReader.

Can you post the stack trace? The error maybe in the code itself. Try changing your construction of buffered reader to this.


InputStream stream = getInputStream("firstNamesMale.src");
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

Yet again, it works perfectly fine in Eclipse, however, it throws the null pointer when run from a jar. Here’s the stack trace. I don’t know what good it will do.

and here’s the methods.


  private static void loadFirstNamesMale(){
		try{
			InputStream url = getInputStream("firstNamesMale.src");
			BufferedReader reader = new BufferedReader(new InputStreamReader(url));
			String line = "";
			while((line = reader.readLine()) != null){
				firstNameMale.add(line);
			}
			System.out.println("Loaded: firstNamesMale.src");
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	private static void loadLastNames(){
		try{
			InputStream url = getInputStream("lastNames.src");
			BufferedReader reader = new BufferedReader(new InputStreamReader(url));
			String line = "";
			while((line = reader.readLine()) != null){
				lastName.add(line);
			}
			System.out.println("Loaded: lastNames.src");
		}catch(Exception e){
			e.printStackTrace();
		}
	}
   private static InputStream getInputStream(String name){
		return Assets.class.getClassLoader().getResourceAsStream("res/" + name);
	}

If it’s working fine in Eclipse and not when running the JAR, then the files you’re trying to load are not being included in the JAR file within a folder called “res”. Is there something you need to do to the folder in Eclipse for this to happen?

It is a critical piece of information. The earlier you share this with people you’re asking for help, the sooner issues get resolved.

It seems like your resource just cannot be found by the InputStream. You have to check if the packages are properly named. Also if you have copied SHC’s code you should check, if youre resources are located in a package called res.:

Have you added the ‘res’ folder to your build path?

Project -> Properties -> Java Build Path -> Source [Tab] -> Add Folder?

In that case omit the “res/” part of the name since, if you take a look at your bin folder, you will see that there is no actual res folder added into the final package. Simply use “/” + name.

You can add an additional folder under the res folder and call it “names” - in that case, you would use “/names/” + name.

I did like SHC said and created a new package called ‘res’ and used explorer to move the files into there. They get exported automatically and the folder and all of the files are present in the exported JAR. When I go to the bin folder, there is a folder called res.

is the ‘res’ folder under the ‘src’ folder? Also package/folder - same thing.

Yeah, this should help to clear things up.

and all the images and .src files are in ‘res’

Personally I would take out the res folder from under “src” and add the “res” folder to the Java Build Path (the src folder is by default already in the Java Build Path).

However, in your case it should work by simply using “/res/resourceName.src”.

Also, you should use the “Reverse Domain Name Notation” http://en.wikipedia.org/wiki/Reverse_domain_name_notation in your “toasted.com” package. I.e, rename it “com.toasted”.

[EDIT]: Also, I like to use the “Navigator” instead of the “Package Explorer” in Eclipse - not that it matters.

It’s working for me. Here’s my structure of eclipse with Space Invaders project.

This is my load image method.


public static Image loadImage(String name)
{
    Image img = null;
    if (cache == null)
    {
        cache = new HashMap < String, Image > ();
    }
    if (cache.containsKey(name))
    {
        img = cache.get(name);
    }
    else
    {
        try
        {
            img = new ImageIcon(Game.class.getClassLoader().getResource(name)).getImage();
            cache.put(name, img);
        }
        catch (Exception e)
        {
            System.err.println("Error loading image : " + name + "\nFatal error. The program is exiting.");
        }
    }
    return img;
}

And I load the images lile


image = loadImage("resources/alien_ship.png");

It works for me perfectly.

@SHC
I’m not having any trouble loading images. They load perfectly fine. However, the trouble is with InputStreams.

@jonjava
So, I moved the ‘res’ folder from ‘src’ and put it alongside the ‘src’ folder. Then I added it to the build path. Images still load fine, but the .src files will not load. The problem has got to be somewhere in this line.

		return Assets.class.getClassLoader().getResourceAsStream("/" + name);

As it is always returning null.

Seems like you’re not getting the classLoader from an instantiated object in which case the “getClassLoader()” will return null iirc. Try changing that to:

 return Assets.class.getResourceAsStream("/" + name);

http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html

The nullPointerException suggests that the InputStream is null. In the Constructor of the InputStreamReader’s superclass Reader you will find this:


if (lock == null) {
      throw new NullPointerException();
}

lock is in that case the InputStream Object created from getResourceAsStream(). This is what getResourceAsStream() returns:


public InputStream getResourceAsStream(String name) {
      URL url = getResource(name);
      try {
            return url != null ? url.openStream() : null;
      } catch (IOException e) {
            return null;
      }
}

So your URL is definetely null. This (as we all know) only happens if your path is not valid.

Ok, so I changed it to:

return Assets.class.getResourceAsStream("/" + name);

and that works fine and dandy in eclipse, but still throws a null pointer when run from a jar.

Yes, indeed, sirkarpfen.

class and ClassLoader are similar and different. Take a look at this stackoverflow post:

try with the ClassLoader without the leading dash:

return Assets.class.getClassLoader().getResourceAsStream(name);

I did as you said, and both worked perfectly in the workspace, but STILL not when i export. I double checked that the files made it into the jar as well.