How can I access a folder inside of a resource folder from inside my jar File?

JavaListResourcesDirectory

Java Problem Overview


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...

Java Solutions


Solution 1 - Java

Finally, I found the solution:

final String path = "sample/folder";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());

if(jarFile.isFile()) {  // Run with JAR file
    final JarFile jar = new JarFile(jarFile);
    final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
    while(entries.hasMoreElements()) {
        final String name = entries.nextElement().getName();
        if (name.startsWith(path + "/")) { //filter according to the path
            System.out.println(name);
        }
    }
    jar.close();
} else { // Run with IDE
    final URL url = Launcher.class.getResource("/" + path);
    if (url != null) {
        try {
            final File apps = new File(url.toURI());
            for (File app : apps.listFiles()) {
                System.out.println(app);
            }
        } catch (URISyntaxException ex) {
            // never happens
        }
    }
}

The second block just work when you run the application on IDE (not with jar file), You can remove it if you don't like that.

Solution 2 - Java

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/");

Solution 3 - Java

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.

Solution 4 - Java

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

Solution 5 - Java

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+.

Solution 6 - Java

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

Solution 7 - Java

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.

Solution 8 - Java

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");
                    }
                }
            }
             

Solution 9 - Java

If you are using Spring you can use org.springframework.core.io.support.PathMatchingResourcePatternResolver and deal with Resource objects rather than files. This works when running inside and outside of a Jar file.

PathMatchingResourcePatternResolver r = new PathMatchingResourcePatternResolver();
Resource[] resources = r.getResources("/myfolder/*");

Then you can access the data using getInputStream and the filename from getFilename.

Note that it will still fail if you try to use the getFile while running from a Jar.

Solution 10 - Java

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);

Solution 11 - Java

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

Solution 12 - Java

This link tells you how.

The magic is the getResourceAsStream() method :

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMostafa ZeinaliView Question on Stackoverflow
Solution 1 - Javauser1079877View Answer on Stackoverflow
Solution 2 - JavaGlen BestView Answer on Stackoverflow
Solution 3 - JavaCheng LinView Answer on Stackoverflow
Solution 4 - JavaSQL.injectionView Answer on Stackoverflow
Solution 5 - JavahummingVView Answer on Stackoverflow
Solution 6 - JavaQy ZuoView Answer on Stackoverflow
Solution 7 - JavaEmmanuel TouzeryView Answer on Stackoverflow
Solution 8 - JavaAnshul ZunkeView Answer on Stackoverflow
Solution 9 - JavacatputerView Answer on Stackoverflow
Solution 10 - JavaLoveLovelyJavaView Answer on Stackoverflow
Solution 11 - JavaPeter KriensView Answer on Stackoverflow
Solution 12 - JavaJames AndersonView Answer on Stackoverflow