[SOLVED] Load resources from a jar

Issue

This Content is from Stack Overflow. Question asked by IDontWantToMakeAnotherAccount

How can I get the file object from the resource folder from a built jar? I can easily do it from the IDE by doing the following however this does not work with jar files. The code bellow just creates a copy of a file in my resource folder and saves it on the users machine.

            final ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            final InputStream configIs = classloader.getResourceAsStream("config.yml");
            
            if(configIs != null) {
                final File configFile = new File(chosenPath + "/config.yml");
                Files.copy(configIs, configFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                configIs.close();
            }

I have been trying to figure out how to do the same from within a jar without much success even after reading many other articles. Based on my research the following was suggested. The code bellow loops through all of the paths that reference the resource path. This produces a 500+ KB text file so I am not exactly sure which one is correct but even if I find the correct one what do I do with it? Since the last if statement checks name starts with resourcePath I assume this is the correct entry

Entry:config.yml path:resources/problems.json

But how do I go from that to an input stream? If there is a better way of doing this let me know but so far I have not found any other resources on this topic.

        if(jarFile.exists() && jarFile.isFile()) {  // Run with JAR file
        System.out.println("Run as jar");
        try {
            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();
                System.out.println("Entry:" + name + " path:" + resourcePath);
                if (name.startsWith(resourcePath)) { //filter according to the path
                    System.out.println(name);
                }
            }
            jar.close();
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }



Solution

Perhaps this will help a bit:

/**
 * Text files loaded with this method should work either within the IDE or your 
 * distributive JAR file.<br><br>
 * 
 * <b>Example Usage:</b><pre>
 * {@code 
 *  try {
 *       List<String> list = loadFileFromResources("/resources/textfiles/data_2.txt");
 *       for (String str : list) {
 *           System.out.println(str);
 *       }
 *   }
 *   catch (IOException ex) {
 *       System.err.println(ex);
 *   } }</pre><br>
 * 
 * As shown in the example usage above the file path requires the Resource 
 * folder to be named "resources" which also contains a sub-folder named 
 * "textfiles". This resource folder is to be located directly within the 
 * Project "src" folder, for example:<pre>
 * 
 *      ProjectDirectoryName
 *          bin
 *          build 
 *          lib
 *          dist
 *          src
 *              resources
 *                  images
 *                      myImage_1.png
 *                      myImage_2.jpg
 *                      myImage_3.gif
 *                  textfiles
 *                      data_1.txt
 *                      data_2.txt
 *                      data_3.txt
 *          test</pre><br>
 * 
 * Upon creating the resources/images and resources/textfiles folders within 
 * the src folder, your IDE should have created two packages within the Project 
 * named resources.images and resources.textfiles. Images would of course be 
 * related to the resources.images package and Text Files would be related to 
 * the resources.textfiles package.<br>
 * 
 * @param filePath (String) Based on the example folder structure above this 
 * would be (as an example):<pre>
 * 
 *    <b>  "/resources/textfiles/data_2.txt"  </b></pre>
 * 
 * @return ({@code List<String>}) A List of String containing the file's content.
 */
public List<String> loadFileFromResources(String filePath) throws java.io.IOException {
    List<String> lines = new ArrayList<>();
    try (java.io.InputStream in = getClass().getResourceAsStream(filePath);
    java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(in))) {
        String line;
        while ((line = reader.readLine()) != null) {
            lines.add(line);
        }
        reader.close();
    }
    return lines;
}


This Question was asked in StackOverflow by IDontWantToMakeAnotherAccount and Answered by DevilsHnd It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?