[java] How can I get a resource "Folder" from inside my jar File?

I have a resources folder/package in the root of my project, I "don't" want to load a certain File. If I wanted to load a certain File, I would use class.getResourceAsStream and I would be fine!! What I actually want to do is to load a "Folder" within the resources folder, loop on the Files inside that Folder and get a Stream to each file and read in the content... Assume that the File names are not determined before runtime... What should I do? Is there a way to get a list of the files inside a Folder in your jar File? Notice that the Jar file with the resources is the same jar file from which the code is being run...

Thanks in advance...

This question is related to java list resources directory

The answer is


I had the same problem at hands while i was attempting to load some hadoop configurations from resources packed in the jar... on both the IDE and on jar (release version).

I found java.nio.file.DirectoryStream to work the best to iterate over directory contents over both local filesystem and jar.

String fooFolder = "/foo/folder";
....

ClassLoader classLoader = foofClass.class.getClassLoader();
try {
    uri = classLoader.getResource(fooFolder).toURI();
} catch (URISyntaxException e) {
    throw new FooException(e.getMessage());
} catch (NullPointerException e){
    throw new FooException(e.getMessage());
}

if(uri == null){
    throw new FooException("something is wrong directory or files missing");
}

/** i want to know if i am inside the jar or working on the IDE*/
if(uri.getScheme().contains("jar")){
    /** jar case */
    try{
        URL jar = FooClass.class.getProtectionDomain().getCodeSource().getLocation();
        //jar.toString() begins with file:
        //i want to trim it out...
        Path jarFile = Paths.get(jar.toString().substring("file:".length()));
        FileSystem fs = FileSystems.newFileSystem(jarFile, null);
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(fs.getPath(fooFolder));
        for(Path p: directoryStream){
            InputStream is = FooClass.class.getResourceAsStream(p.toString()) ;
        performFooOverInputStream(is);
        /** your logic here **/
            }
    }catch(IOException e) {
        throw new FooException(e.getMessage());     
    }
}
else{
    /** IDE case */
    Path path = Paths.get(uri);
    try {
        DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
        for(Path p : directoryStream){
            InputStream is = new FileInputStream(p.toFile());
            performFooOverInputStream(is);
        }
    } catch (IOException _e) {
        throw new FooException(_e.getMessage());
    }
}

Below code gets .yaml files from a custom resource directory.

ClassLoader classLoader = this.getClass().getClassLoader();
            URI uri = classLoader.getResource(directoryPath).toURI();
    
            if("jar".equalsIgnoreCase(uri.getScheme())){
                Pattern pattern = Pattern.compile("^.+" +"/classes/" + directoryPath + "/.+.yaml$");
                log.debug("pattern {} ", pattern.pattern());
                ApplicationHome home = new ApplicationHome(SomeApplication.class);
                JarFile file = new JarFile(home.getSource());
                Enumeration<JarEntry>  jarEntries = file.entries() ;
                while(jarEntries.hasMoreElements()){
                    JarEntry entry = jarEntries.nextElement();
                    Matcher matcher = pattern.matcher(entry.getName());
                    if(matcher.find()){
                        InputStream in =
                                file.getInputStream(entry);
                        //work on the stream
    
    
                    }
                }
    
            }else{
                //When Spring boot application executed through Non-Jar strategy like through IDE or as a War.
    
                String path = uri.getPath();
                File[] files = new File(path).listFiles();
               
                for(File file: files){
                    if(file != null){
                        try {
                            InputStream is = new FileInputStream(file);
                           //work on stream
                            
                        } catch (Exception e) {
                            log.error("Exception while parsing file yaml file {} : {} " , file.getAbsolutePath(), e.getMessage());
                        }
                    }else{
                        log.warn("File Object is null while parsing yaml file");
                    }
                }
            }
             

Simple ... use OSGi. In OSGi you can iterate over your Bundle's entries with findEntries and findPaths.


The following code returns the wanted "folder" as Path regardless of if it is inside a jar or not.

  private Path getFolderPath() throws URISyntaxException, IOException {
    URI uri = getClass().getClassLoader().getResource("folder").toURI();
    if ("jar".equals(uri.getScheme())) {
      FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
      return fileSystem.getPath("path/to/folder/inside/jar");
    } else {
      return Paths.get(uri);
    }
  }

Requires java 7+.


This link tells you how.

The magic is the getResourceAsStream() method :

InputStream is = 
this.getClass().getClassLoader().getResourceAsStream("yourpackage/mypackage/myfile.xml")

Another solution, you can do it using ResourceLoader like this:

import org.springframework.core.io.Resource;
import org.apache.commons.io.FileUtils;

@Autowire
private ResourceLoader resourceLoader;

...

Resource resource = resourceLoader.getResource("classpath:/path/to/you/dir");
File file = resource.getFile();
Iterator<File> fi = FileUtils.iterateFiles(file, null, true);
while(fi.hasNext()) {
    load(fi.next())
}

As the other answers point out, once the resources are inside a jar file, things get really ugly. In our case, this solution:

https://stackoverflow.com/a/13227570/516188

works very well in the tests (since when the tests are run the code is not packed in a jar file), but doesn't work when the app actually runs normally. So what I've done is... I hardcode the list of the files in the app, but I have a test which reads the actual list from disk (can do it since that works in tests) and fails if the actual list doesn't match with the list the app returns.

That way I have simple code in my app (no tricks), and I'm sure I didn't forget to add a new entry in the list thanks to the test.


I know this is many years ago . But just for other people come across this topic. What you could do is to use getResourceAsStream() method with the directory path, and the input Stream will have all the files name from that dir. After that you can concat the dir path with each file name and call getResourceAsStream for each file in a loop.


Try the following.
Make the resource path "<PathRelativeToThisClassFile>/<ResourceDirectory>" E.g. if your class path is com.abc.package.MyClass and your resoure files are within src/com/abc/package/resources/:

URL url = MyClass.class.getResource("resources/");
if (url == null) {
     // error - missing folder
} else {
    File dir = new File(url.toURI());
    for (File nextFile : dir.listFiles()) {
        // Do something with nextFile
    }
}

You can also use

URL url = MyClass.class.getResource("/com/abc/package/resources/");

Inside my jar file I had a folder called Upload, this folder had three other text files inside it and I needed to have an exactly the same folder and files outside of the jar file, I used the code below:

URL inputUrl = getClass().getResource("/upload/blabla1.txt");
File dest1 = new File("upload/blabla1.txt");
FileUtils.copyURLToFile(inputUrl, dest1);

URL inputUrl2 = getClass().getResource("/upload/blabla2.txt");
File dest2 = new File("upload/blabla2.txt");
FileUtils.copyURLToFile(inputUrl2, dest2);

URL inputUrl3 = getClass().getResource("/upload/blabla3.txt");
File dest3 = new File("upload/Bblabla3.txt");
FileUtils.copyURLToFile(inputUrl3, dest3);

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to list

Convert List to Pandas Dataframe Column Python find elements in one list that are not in the other Sorting a list with stream.sorted() in Java Python Loop: List Index Out of Range How to combine two lists in R How do I multiply each element in a list by a number? Save a list to a .txt file The most efficient way to remove first N elements in a list? TypeError: list indices must be integers or slices, not str Parse JSON String into List<string>

Examples related to resources

Spring Boot access static resources missing scr/main/resources How do I add a resources folder to my Java project in Eclipse Tomcat 8 throwing - org.apache.catalina.webresources.Cache.getResource Unable to add the resource Reading a resource file from within jar How to fix the "508 Resource Limit is reached" error in WordPress? How to get absolute path to file in /resources folder of your project getResourceAsStream returns null How to read file from res/raw by name Load image from resources Resource leak: 'in' is never closed

Examples related to directory

Moving all files from one directory to another using Python What is the reason for the error message "System cannot find the path specified"? Get folder name of the file in Python How to rename a directory/folder on GitHub website? Change directory in Node.js command prompt Get the directory from a file path in java (android) python: get directory two levels up How to add 'libs' folder in Android Studio? How to create a directory using Ansible Troubleshooting misplaced .git directory (nothing to commit)