2

Many tutorials for reading a file from a resources folder use class loader. However, using that method I cannot get past problems with static warnings and the result is always a null pointer exception.

public class Test {
    public static void main(String[] args) {
        StringBuilder contentBuilder=new StringBuilder();
        ClassLoader classLoader=Test.class.getClassLoader();
        File file=new File(classLoader.getSystemResource("test.html").getFile());
        try {
            BufferedReader buffer=new BufferedReader(new FileReader(file));
            String sCurrentLine="";
            while ((sCurrentLine=buffer.readLine())!=null) {
                contentBuilder.append(sCurrentLine);
            }
            buffer.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
        String content=contentBuilder.toString();
        System.out.println("content="+content);
    }
}

The warning from my IDE on the "File" line is:

The static method getSystemResource(String) from the type ClassLoader should be accessed in a static way

I cannot figure out how to eliminate the warning and if I just ignore it and run the code I get a null pointer exception. Why am I getting this and how do I fix it? TIA.

fantaghirocco
  • 4,761
  • 6
  • 38
  • 48
Wt Riker
  • 514
  • 12
  • 24

2 Answers2

1

Test.class.getClassLoader(); obtains a reference to the ClassLoader class from the Class' method public ClassLoader getClassLoader() - see private final ClassLoader classLoader below.

Since you are accessing the ClassLoader class from an object of that class, you're not accessing it in a static way.

From Class.java, Java SE 1.7:

@CallerSensitive
public ClassLoader getClassLoader() {
    ClassLoader cl = getClassLoader0();
    if (cl == null)
        return null;
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
    }
    return cl;
}

// Package-private to allow ClassLoader access
ClassLoader getClassLoader0() { return classLoader; }

// Initialized in JVM not by private constructor
// This field is filtered from reflection access, i.e. getDeclaredField
// will throw NoSuchFieldException
private final ClassLoader classLoader;

In order to access the method in a static way, it has to be called from the class which declares it as static if you want to get rid of the warning:

ClassLoader.getSystemResource("test.html").getFile()

To avoid the NPE the test.html file should be under your source folder.


To respond to your comment, using a method which returns other than a URL solves your problem - see Reading a resource file from within jar.

public class Test {

    public static void main(String[] args) {
        StringBuilder contentBuilder = new StringBuilder();

        InputStream is = Test.class.getResourceAsStream("/test.html");
        try {
            String sCurrentLine;

            BufferedReader buffer = new BufferedReader(new InputStreamReader(is));
            while ((sCurrentLine = buffer.readLine())!=null)
                contentBuilder.append(sCurrentLine);
            buffer.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }

        System.out.println("content=" + contentBuilder.toString());
    }
}
fantaghirocco
  • 4,761
  • 6
  • 38
  • 48
  • I asked in my comment to Shantu if the file path was wrong I'd get a file not found exception rather than null pointer. Assuming you are saying the path is wrong, my path is Test->src->resources->help.html. So would the file path then be 'resources/test.html"? – Wt Riker Jul 04 '18 at 16:41
  • I tried the path 'resources/test.html" and then I got the file not found exception. This is very confusing as now I don't know where the null pointer exception is coming from. Interestingly if I follow the path in the traceback, the file is indeed there. – Wt Riker Jul 04 '18 at 16:53
  • @Wt Riker I've added some more tips: hope it'll help – fantaghirocco Jul 05 '18 at 08:43
  • Thanks but no joy. I think the bottom line is that this problem has to do with the directory structure and finding the target file. I'm stumped. I tried "/test.html", "test.html", "resources/test.html", "src/resources/test.html" but same exception on them all. Including Hearen's suggestion. – Wt Riker Jul 05 '18 at 13:18
  • @Wt Riker I tested the solution above and it works in Eclipse and in a jar with the file in `src` or in `resources`. Anyway... good luck! Double check your file name: *help.html* or *test.html*? ;-) – fantaghirocco Jul 05 '18 at 13:24
  • What was the file path you used when it was in src->resouces? Or do you have resources at the same directory level as src rather than under src? – Wt Riker Jul 05 '18 at 13:26
  • at the same level like Eclipse does: resources should be a **source** folder – fantaghirocco Jul 05 '18 at 13:26
  • Ah ha!!!!!!!!!! The one path I did not try: "/resources/test.html". Thanks. – Wt Riker Jul 05 '18 at 13:28
  • You're welcome. Obvious things are always a pain when debugging :D – fantaghirocco Jul 05 '18 at 13:30
0

Or you can try to read them all at once:

    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    String content;
    try {
        content = new String(Files.readAllBytes(Paths.get(loader.getResource("test.html").toURI())), StandardCharsets.UTF_8);
    } catch (Exception e) {
        e.printStackTrace();
    }

If you are using maven, do please remember to set the resources based on your case (either as Sources Root or Test Sources Root).

By the way, your solution is alright using Test.class.getClassLoader();.

Hearen
  • 7,420
  • 4
  • 53
  • 63