javapackageclasspathclassloaderurlclassloader

Listing and reading all files in a java package within a JAR file not working


I have a package with a list of files within a jar file. The idea is find all files in the package and read the contents of each.

private static final String DATA_DIRECTORY = "this/is/my/package/containing/data/";
try {
            URL url = this.getClass().getClassLoader().getResource(DATA_DIRECTORY);
            if (url.toExternalForm().startsWith("jar:")) {

                try (BufferedReader in = new BufferedReader(
                        new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream(DATA_DIRECTORY)))) {
                    String inputLine;
                    while ((inputLine = in.readLine()) != null) {
                        System.out.println(inputLine);
                    }
                }
            } else {
                try (BufferedReader in = new BufferedReader(
                        new InputStreamReader(url.openStream()))) {
                    String inputLine;
                    while ((inputLine = in.readLine()) != null) {
                        System.out.println(inputLine);
                    }
                }
            }
        } catch (Exception e) {
            System.out.println(e);
        }

Windows Results

[Path] -> file:/D:/path/to/application/lib/my-jarfile.jar!/this/is/my/package/containing/data/

[Files] ->
b2b
b2c
bal
c2b
olp
olq
reg
rev
stat

Linux Results

[Path] -> jar:file:/path/to/application/lib/my-jarfile.jar!/this/is/my/package/containing/data/

[Files] -> []

[available bytes] -> 0

In Windows it works perfectly but in Linux it fails, it shows that the Inputstream has 0 bytes available and I wonder why. I have tried a couple of solutions but none seem to give me the result I am looking for. What or where could I be going wrong ?


Solution

  • So after some more research the above code only worked in the IDE in Windows but for a jar file it was failing hence the result I was getting in Linux and also in Windows.

    Below is the the working solution I am using. It can be rewritten in a much concise manner but because of time I have kept it as is. It works for both Classpath and a Jar file.

    String directory = "/this/is/my/package/containing/data/";
    

    Note that the beginning slash is needed in the package name directory.

    String path = ClassLoader.class.getResource(directory).toExternalForm();
            if (path.startsWith("jar")) {
                try {
                    URL url = new URL(path);
                    System.out.println("JAR URL Name : " + url.toString());
                    JarURLConnection connection = (JarURLConnection) url.openConnection();
                    String jarFileName = connection.getJarFile().getName();
                    System.out.println("JAR File Name : " + jarFileName);
                    try (JarInputStream jarFile = new JarInputStream(new FileInputStream(jarFileName));) {
                        String regex = directory.substring(1);
                        do {
                            try {
                                JarEntry jarEntry = jarFile.getNextJarEntry();
                                if (jarEntry != null) {
                                    String entryName = jarEntry.getName();
                                    if (!regex.equals(entryName) && entryName.contains(regex)) {
                                        System.out.println("JAR Entry Name : " + entryName);
                                        try (InputStream in = YourClassName.class.getClassLoader().getResourceAsStream(entryName);
                                                Scanner scanner = new Scanner(in);) {
                                        //Do something in here                                       
                                        } catch (Exception ex) {
                                            System.out.println(ex);
                                        }
                                    }
                                } else {
                                    break;
                                }
                            } catch (IOException ex) {
                                System.out.println("JAR InputStream Error : " + jarFileName + " - > " + ex);
                                break;
                            }
                        } while (true);
                    }
                } catch (Exception e) {
                    System.out.println("JAR URL Connection Error : " + e);
                }
            } else {
                try {
                    URL url = new URL(path);
                    try (BufferedReader in = new BufferedReader(
                            new InputStreamReader(url.openStream()))) {
                        String fileName;
                        while ((fileName = in.readLine()) != null) {
                            String filePath = directory + fileName;
                            try (InputStream is = ClassLoader.class.getResourceAsStream(filePath);
                                    Scanner scanner = new Scanner(is);) {
                               //Do something here
                            } catch (Exception ex) {
                                System.out.println(ex);
                            }
                        }
                    }
                } catch (Exception e) {
                    System.out.println("Classpath URL Connection Error : " + e);
                }
            }
        }