Search code examples
javaresourcesclassloader

How to Properly Get a File from resources Folder


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.


Solution

  • 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());
        }
    }