Thursday, 2 August 2012

Understanding Absolute and Relative Path with getResourceAsStream()

Not making the difference between absolute and relative paths when loading resources in Java is a common source of errors leading to NullPointerException (NPE).

Assuming the following structure and content in a maven project:

My Project
  |-src
    |-main
      |-java
      | |-SomePackage
      |   |-SomeClass.java
      |-resources
        |-Root.txt
        |-SomePackage
          |-MyData.txt
          |-SomePackage2
            |-MySubData.txt

Content will be re-organized as following in the .jar:
  |-Root.txt
  |-SomePackage
    |-SomeClass.java
    |-MyData.txt
    |-SomePackage2
      |-MySubData.txt

The following indicates what works and what does not work to retrieve resource data:
InputStream IS;

IS = SomeClass.class.getResourceAsStream(
    "Root.txt"); // Not OK

IS = SomeClass.class.getResourceAsStream(
    "/Root.txt"); // OK

IS = SomeClass.class.getResourceAsStream(
    "/MyData.txt"); // Not OK

IS = SomeClass.class.getResourceAsStream(
    "MyData.txt"); // OK

IS = SomeClass.class.getResourceAsStream(
    "/SomePackage/MyData.txt"); // OK

IS = SomeClass.class.getResourceAsStream(
    "SomePackage/MyData.txt"); // Not OK

IS = SomeClass.class.getResourceAsStream(
    "MySubData.txt"); // Not OK

IS = SomeClass.class.getResourceAsStream(
    "SomePackage/SomePackage2/MySubData.txt"); // OK

IS = SomeClass.class.getResourceAsStream(
    "/SomePackage/SomePackage2/MySubData.txt"); // Not OK

IS = SomeClass.class.getResourceAsStream(
    "/SomePackage2/MySubData.txt"); // Not OK

IS = SomeClass.class.getResourceAsStream(
    "SomePackage2/MySubData.txt"); // OK

getResourceAsStream() operates relative to the package corresponding to the called Class instance.