1

My files are located under projectRoot/src/main/resources/levels/

enter image description here

If I call Utils.getFileNamesInDirectory("src/main/resources/levels"), it works.
But when project is packaged, levels directory is placed under root of .jar.
How can I made this dynamic in static class? i.e src/main/resources/
So that code will run within eclipse and as standalone jar.

Code to list files in directory ..

public class Utils {
    public static List<String> getFileNamesInDirectory(String directory){

        List<String> results = new ArrayList<String>();

        File[] files = new File(directory).listFiles(new FilenameFilter() {
            public boolean accept(File dir, String filename) {
                return filename.endsWith(".json");
            }
        });

        for (File file : files) {
            if (file.isFile()) {
                results.add(file.getName());
            }
        }

        Collections.sort(results);

        return results;
    }
}

Updated

I've moved to using getResourceAsStream (as getResource was causing IllegalArgumentException: URI is not hierarchical) and I'm able to list files in a directory within Eclipse.

public static List<String> getFileNamesInDirectory(String directory){

        List<String> results = new ArrayList<String>();
        InputStream in = Utils.class.getResourceAsStream("/" + directory);
        BufferedReader rdr = new BufferedReader(new InputStreamReader(in));
        String line;

        try {

            while ((line = rdr.readLine()) != null) {
                System.out.println("file: " + line);
                results.add(new File(line).getName());
            }

            rdr.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        Collections.sort(results);

        return results;
    }

But when I run it as standalone .jar I get the following error on this line: while ((line = rdr.readLine()) != null) {
Why does it not work outside Eclipse?

Exception in thread "main" java.lang.NullPointerException
    at java.io.FilterInputStream.read(FilterInputStream.java:133)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:322)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:364)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:210)
    at java.io.InputStreamReader.read(InputStreamReader.java:205)
    at java.io.BufferedReader.fill(BufferedReader.java:165)
    at java.io.BufferedReader.readLine(BufferedReader.java:328)
    at java.io.BufferedReader.readLine(BufferedReader.java:393)
    at com.app.tools.Utils.getFileNamesInDirectory(Utils.java:31)
bobbyrne01
  • 6,295
  • 19
  • 80
  • 150

1 Answers1

3

The reason your code works in Eclipse is that Eclipse launches the java process from the project directory and we can assume the path provided in

Utils.getFileNamesInDirectory("src/main/resources/levels")

is relative to the current working directory (the project directory). Since the file system location <project-directory>/src/main/resources/levels exists, it can be found and returned to you.

src/main/resources is a Maven convention meant to hold resources that will eventually end up in the classpath when the project is compiled/built/deployed. To retrieve resources from the classpath you use Class#getResource(String), ClassLoader#getResource(String) and/or ClassLoader#getSystemResource(String).

Now, although there are ways to list resources in the classpath, you should not typically do this. If you need a resource, you know it by name and can therefore use one of the methods listed above to get it.

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724