IO exception catch

OK, so I know I’ve posted ALOT in the last few days but I could really do with your help on this one.

The following code attempts to read a text file to obtain and store information about where it should put bricks(tiles) on the screen and what image it should paint them.

When run it tells me that it begins reading the file (due to a out.println) and then tells me that it has an error again due to println. I have put another println in for debugging purposes within the while loop and found that it doesn’t get past the first branch, I can’t see why, here’s the code:

{ 
    String imsFNm = IMAGE_DIR + fnm;
    System.out.println("Reading bricks file: " + imsFNm);

    int numStripImages = -1;
    int numBricksLines = 0;
    try {
      BufferedReader br = new BufferedReader( new FileReader(imsFNm));
      String line;
      char ch;
      while((line = br.readLine()) != null) {
        if (line.length() == 0)  // ignore a blank line
            continue;
        System.out.println("Break 1");
        if (line.startsWith("//"))   // ignore a comment line
          continue;
        ch = Character.toLowerCase( line.charAt(0) );
        if (ch == 's')  // an images strip
          numStripImages = getStripImages(line);
        else {  // a bricks map line
          if (numBricksLines > MAX_BRICKS_LINES) 
            System.out.println("Max reached, skipping bricks line: " + line);
          else if (numStripImages == -1) 
            System.out.println("No strip image, skipping bricks line: " + line);
          else {
            storeBricks(line, numBricksLines, numStripImages);
            numBricksLines++;
          }
        }
      }
      br.close();
    } 
    catch (IOException e) 
    { System.out.println("Error reading file: " + imsFNm);
      System.exit(1);
    }

The debugging println prints “break 1”, but when ran it doesn’t reach this branch, this is the output it produces:

Reading bricks file: Images/bricksInfo.txt
Error reading file: Images/bricksInfo.txt
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)

I know that the file paths are correct and that the code points to the right file, so I can’t explain this, any help would be appreciated, thanks.


catch (IOException e) 
 { 
   System.out.println("Error reading file: " + imsFNm);
   System.exit(1);
}

Never ever swallow the given cause of an exception.
So, print e.getMessage() and see whats going on…

cheers that was a great help, in fact it turns out it can’t find the file specified, although I can’t understand why, here’s the file structure:

bricksInfo.txt is clearly in the correct path and the println tells us the code points to it, what’s going on?

Maybe “labrat” is not your current directory when running ?

a fair point, but there are two other almost identical bits of code that deal with sound clips and images, they both use .txt files contained within the LabRat directory, so I don’t think that could be the answer (they run before bricksManager and the log shows that they run successfully).

[EDIT]: In fact ImagesLoader uses a text file from “LabRat/Images”, the same directory that bricksInfo.txt is stored.

The path should be relative to your project’s root folder. It’s only relative to your class file if you use Class.getResource() if I remember correctly.

So any idea as to why it can’t find bricksInfo.txt then?

Load your image as a resource, not a file. Something like this:


InputStream is = getClass().getClassLoader().getResourceAsStream("/labrat/Images/" + fnm);
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));

If you do want it relative to your package, replace the first line with this instead:


InputStream is = getClass().getResourceAsStream("Images/" + fnm);

Oh also notice the encoding: you should always give an encoding, and that’s a reason to not use FileReader, which doesn’t take one.

Ok, so I put in the code you suggested and when run the log produces a NullPointerException:

Exception in thread "main" java.lang.NullPointerException
	at java.io.Reader.<init>(Reader.java:78)
	at java.io.InputStreamReader.<init>(InputStreamReader.java:97)
	at labrat.BricksManager.loadBricksFile(BricksManager.java:140)

suggesting to me that it still can’t find the text file?

I know the answer, but I’m going to break into “teaching to fish” mode and ask you to find out what’s null here. Trust your initial instinct. If you suspect it’s still not finding the file, try doing something like URL res = getClass().getClassLoader().getResource(…) then printing res and seeing if the filename or jar path name looks right.

so I println’d “res” and it returned “null”

does this mean there’s an issue with my “fnm” variable?

It means it failed to find a resource with that name, so it’s probably an issue with what was passed in, yes. What’s the full path you pass in to getResource()? Also, is labrat at the root of your packages? It’s difficult to debug this stuff on the forum without a full file to work from (which would have a package statement and probably the value of IMAGE_DIR)

public class BricksManager
{
  private final static String IMAGE_DIR = "Images/";

The path I put into the code to direct it to bricksInfo.txt is “Images + fnm” (fnm = bricksInfo.txt) meaning that imsFnm = Images/bricksInfo.txt

The only problem I have with your explanation is that there are two other classes that use the same method to load images, ImagesLoader, and sound clips, ClipsLoader. And they run with no issues. I don’t understand why this would be any different?

If you have a relative path, you need to use getClass().getResourceAsStream(), i.e. leave off the getClassLoader() part. That’ll load the resource relative to the location of the class doing the loading. The classes that are working are in the ‘labrat’ package, whereas the class you’re testing either isn’t in the same package, or is using the getClassLoader() version, which is an absolute path regardless of whether it starts with a ‘/’ or not.

I prefer to use relative paths only for default config files like properties, and absolute paths (starting with a ‘/’) for global resources like images. It saves a lot of confusion like the kind you’re experiencing.

First of all, thankyou that has worked and now everything runs smoothly.

But for the sake of my learning and my mind, I know that bricksmanager is in the LabRat package, as is bricksInfo and the assets it refers to, so why did that make a difference?

I’m jumping in kind of late, and am not following all the details. But I will venture to answer the last question:

[quote]But for the sake of my learning and my mind, I know that bricksmanager is in the LabRat package, as is bricksInfo and the assets it refers to, so why did that make a difference?
[/quote]
There are two methods commonly used in loading resources:

  • getResource()
  • getResourceAsStream()

Qualitatively different assets (images vs. text files vs. sounds) will require that you use the correct one of these two. You may have gotten the two methods interchanged or mixed up at some point.

Secondly, the method getClass() refers to the current class, which may not be in the base location. If this class is in a subfolder or subpackage, it would have a different location relative to your Images folder.

Those are the two main reasons that I can think of that might explain why one load worked and another didn’t.

It gets more confusing (to me, anyway :slight_smile: ) when loading resources from jar files. When I have doubts, I consult the following Java tutorial. The section “Loading Images using getResource” has examples of various scenarios:

http://docs.oracle.com/javase/tutorial/uiswing/components/icon.html

P.S. When loading audio assets, it is better to use URLs than InputStreams (which can sometimes throw mark/reset errors).

Well having taken a good hard look at all of the code, including the 2 classes that already worked I realised that the BricksManager was missing an input stream in the first place, so how was bufferedReader meant to find the file.

BUT I have learned a lot about input streams, so I can’t thank sproingie enough for his patience and willing to teach me and for philfrei for the explanation and tutorial link :smiley:

Who said the internet is full of trolls :stuck_out_tongue: (or maybe java developers actually have souls!) ?