[java] Reading a resource file from within jar

I would like to read a resource from within my jar like so:

File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferedReader reader = new BufferedReader(new FileReader(file));

//Read the file

and it works fine when running it in Eclipse, but if I export it to a jar, and then run it, there is an IllegalArgumentException:

Exception in thread "Thread-2"
java.lang.IllegalArgumentException: URI is not hierarchical

and I really don't know why but with some testing I found if I change

file = new File(getClass().getResource("/file.txt").toURI());

to

file = new File(getClass().getResource("/folder/file.txt").toURI());

then it works the opposite (it works in jar but not eclipse).

I'm using Eclipse and the folder with my file is in a class folder.

This question is related to java file jar resources embedded-resource

The answer is


Make sure that you work with the correct separator. I replaced all / in a relative path with a File.separator. This worked fine in the IDE, however did not work in the build JAR.


You can use class loader which will read from classpath as ROOT path (without "/" in the beginning)

InputStream in = getClass().getClassLoader().getResourceAsStream("file.txt"); 
BufferedReader reader = new BufferedReader(new InputStreamReader(in));

I had this problem before and I made fallback way for loading. Basically first way work within .jar file and second way works within eclipse or other IDE.

public class MyClass {

    public static InputStream accessFile() {
        String resource = "my-file-located-in-resources.txt";

        // this is the path within the jar file
        InputStream input = MyClass.class.getResourceAsStream("/resources/" + resource);
        if (input == null) {
            // this is how we load file within editor (eg eclipse)
            input = MyClass.class.getClassLoader().getResourceAsStream(resource);
        }

        return input;
    }
}

In my case I finally made it with

import java.lang.Thread;
import java.io.BufferedReader;
import java.io.InputStreamReader;

final BufferedReader in = new BufferedReader(new InputStreamReader(
      Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt"))
); // no initial slash in file.txt

If you are using spring, then you can use the the following method to read file from src/main/resources:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.springframework.core.io.ClassPathResource;

  public String readFileToString(String path) throws IOException {

    StringBuilder resultBuilder = new StringBuilder("");
    ClassPathResource resource = new ClassPathResource(path);

    try (
        InputStream inputStream = resource.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {

      String line;

      while ((line = bufferedReader.readLine()) != null) {
        resultBuilder.append(line);
      }

    }

    return resultBuilder.toString();
  }

Below code works with Spring boot(kotlin):

val authReader = InputStreamReader(javaClass.getResourceAsStream("/file1.json"))

This code works both in Eclipse and in Exported Runnable JAR

private String writeResourceToFile(String resourceName) throws IOException {
    File outFile = new File(certPath + File.separator + resourceName);

    if (outFile.isFile())
        return outFile.getAbsolutePath();
    
    InputStream resourceStream = null;
    
    // Java: In caso di JAR dentro il JAR applicativo 
    URLClassLoader urlClassLoader = (URLClassLoader)Cypher.class.getClassLoader();
    URL url = urlClassLoader.findResource(resourceName);
    if (url != null) {
        URLConnection conn = url.openConnection();
        if (conn != null) {
            resourceStream = conn.getInputStream();
        }
    }
    
    if (resourceStream != null) {
        Files.copy(resourceStream, outFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        return outFile.getAbsolutePath();
    } else {
        System.out.println("Embedded Resource " + resourceName + " not found.");
    }
    
    return "";
}   

For some reason classLoader.getResource() always returned null when I deployed the web application to WildFly 14. getting classLoader from getClass().getClassLoader() or Thread.currentThread().getContextClassLoader() returns null.

getClass().getClassLoader() API doc says,

"Returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class was loaded by the bootstrap class loader."

may be if you are using WildFly and yours web application try this

request.getServletContext().getResource() returned the resource url. Here request is an object of ServletRequest.


Up until now (December 2017), this is the only solution I found which works both inside and outside the IDE.

Use PathMatchingResourcePatternResolver

Note: it works also in spring-boot

In this example I'm reading some files located in src/main/resources/my_folder:

try {
    // Get all the files under this inner resource folder: my_folder
    String scannedPackage = "my_folder/*";
    PathMatchingResourcePatternResolver scanner = new PathMatchingResourcePatternResolver();
    Resource[] resources = scanner.getResources(scannedPackage);

    if (resources == null || resources.length == 0)
        log.warn("Warning: could not find any resources in this scanned package: " + scannedPackage);
    else {
        for (Resource resource : resources) {
            log.info(resource.getFilename());
            // Read the file content (I used BufferedReader, but there are other solutions for that):
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                // ...
                // ...                      
            }
            bufferedReader.close();
        }
    }
} catch (Exception e) {
    throw new Exception("Failed to read the resources folder: " + e.getMessage(), e);
}

I have found a fix

BufferedReader br = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream(path)));

Replace "Main" with the java class you coded it in. replace "path" with the path within the jar file.

for example, if you put State1.txt in the package com.issac.state, then type the path as "/com/issac/state/State1" if you run Linux or Mac. If you run Windows then type the path as "\com\issac\state\State1". Don't add the .txt extension to the file unless the File not found exception occurs.


To access a file in a jar you have two options:

  • Place the file in directory structure matching your package name (after extracting .jar file, it should be in the same directory as .class file), then access it using getClass().getResourceAsStream("file.txt")

  • Place the file at the root (after extracting .jar file, it should be in the root), then access it using Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt")

The first option may not work when jar is used as a plugin.


If you wanna read as a file, I believe there still is a similar solution:

    ClassLoader classLoader = getClass().getClassLoader();
    File file = new File(classLoader.getResource("file/test.xml").getFile());

The problem is that certain third party libraries require file pathnames rather than input streams. Most of the answers don't address this issue.

In this case, one workaround is to copy the resource contents into a temporary file. The following example uses jUnit's TemporaryFolder.

    private List<String> decomposePath(String path){
        List<String> reversed = Lists.newArrayList();
        File currFile = new File(path);
        while(currFile != null){
            reversed.add(currFile.getName());
            currFile = currFile.getParentFile();
        }
        return Lists.reverse(reversed);
    }

    private String writeResourceToFile(String resourceName) throws IOException {
        ClassLoader loader = getClass().getClassLoader();
        InputStream configStream = loader.getResourceAsStream(resourceName);
        List<String> pathComponents = decomposePath(resourceName);
        folder.newFolder(pathComponents.subList(0, pathComponents.size() - 1).toArray(new String[0]));
        File tmpFile = folder.newFile(resourceName);
        Files.copy(configStream, tmpFile.toPath(), REPLACE_EXISTING);
        return tmpFile.getAbsolutePath();
    }

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 file

Gradle - Move a folder from ABC to XYZ Difference between opening a file in binary vs text Angular: How to download a file from HttpClient? Python error message io.UnsupportedOperation: not readable java.io.FileNotFoundException: class path resource cannot be opened because it does not exist Writing JSON object to a JSON file with fs.writeFileSync How to read/write files in .Net Core? How to write to a CSV line by line? Writing a dictionary to a text file? What are the pros and cons of parquet format compared to other formats?

Examples related to jar

Running JAR file on Windows 10 Add jars to a Spark Job - spark-submit Deploying Maven project throws java.util.zip.ZipException: invalid LOC header (bad signature) java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonFactory Maven Error: Could not find or load main class Where can I download mysql jdbc jar from? Access restriction: The type 'Application' is not API (restriction on required library rt.jar) Create aar file in Android Studio Checking Maven Version Creating runnable JAR with Gradle

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 embedded-resource

Reading a resource file from within jar File loading by getClass().getResource() How do I add an image to a JButton How to read embedded resource text file Could not find any resources appropriate for the specified culture or the neutral culture Loop through all the resources in a .resx file Storing WPF Image Resources