[java] How to read a file from jar in Java?

I want to read an XML file that is located inside one of the jars included in my class path. How can I read any file which is included in the jar?

This question is related to java file-io jar

The answer is


If you want to read that file from inside your application use:

InputStream input = getClass().getResourceAsStream("/classpath/to/my/file");

The path starts with "/", but that is not the path in your file-system, but in your classpath. So if your file is at the classpath "org.xml" and is called myxml.xml your path looks like "/org/xml/myxml.xml".

The InputStream reads the content of your file. You can wrap it into an Reader, if you want.

I hope that helps.


A JAR is basically a ZIP file so treat it as such. Below contains an example on how to extract one file from a WAR file (also treat it as a ZIP file) and outputs the string contents. For binary you'll need to modify the extraction process, but there are plenty of examples out there for that.

public static void main(String args[]) {
    String relativeFilePath = "style/someCSSFile.css";
    String zipFilePath = "/someDirectory/someWarFile.war";
    String contents = readZipFile(zipFilePath,relativeFilePath);
    System.out.println(contents);
}

public static String readZipFile(String zipFilePath, String relativeFilePath) {
    try {
        ZipFile zipFile = new ZipFile(zipFilePath);
        Enumeration<? extends ZipEntry> e = zipFile.entries();

        while (e.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) e.nextElement();
            // if the entry is not directory and matches relative file then extract it
            if (!entry.isDirectory() && entry.getName().equals(relativeFilePath)) {
                BufferedInputStream bis = new BufferedInputStream(
                        zipFile.getInputStream(entry));
                // Read the file
                    // With Apache Commons I/O
                 String fileContentsStr = IOUtils.toString(bis, "UTF-8");

                    // With Guava
                //String fileContentsStr = new String(ByteStreams.toByteArray(bis),Charsets.UTF_8);
                // close the input stream.
                bis.close();
                return fileContentsStr;
            } else {
                continue;
            }
        }
    } catch (IOException e) {
        logger.error("IOError :" + e);
        e.printStackTrace();
    }
    return null;
}

In this example I'm using Apache Commons I/O and if you are using Maven here is the dependency:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

Check first your class loader.

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

if (classLoader == null) {
    classLoader = Class.class.getClassLoader();
}

classLoader.getResourceAsStream("xmlFileNameInJarFile.xml");

// xml file location at xxx.jar
// + folder
// + folder
// xmlFileNameInJarFile.xml

Ah, this is one of my favorite subjects. There are essentially two ways you can load a resource through the classpath:

Class.getResourceAsStream(resource)

and

ClassLoader.getResourceAsStream(resource)

(there are other ways which involve getting a URL for the resource in a similar fashion, then opening a connection to it, but these are the two direct ways).

The first method actually delegates to the second, after mangling the resource name. There are essentially two kinds of resource names: absolute (e.g. "/path/to/resource/resource") and relative (e.g. "resource"). Absolute paths start with "/".

Here's an example which should illustrate. Consider a class com.example.A. Consider two resources, one located at /com/example/nested, the other at /top, in the classpath. The following program shows nine possible ways to access the two resources:

package com.example;

public class A {

    public static void main(String args[]) {

        // Class.getResourceAsStream
        Object resource = A.class.getResourceAsStream("nested");
        System.out.println("1: A.class nested=" + resource);

        resource = A.class.getResourceAsStream("/com/example/nested");
        System.out.println("2: A.class /com/example/nested=" + resource);

        resource = A.class.getResourceAsStream("top");
        System.out.println("3: A.class top=" + resource);

        resource = A.class.getResourceAsStream("/top");
        System.out.println("4: A.class /top=" + resource);

        // ClassLoader.getResourceAsStream
        ClassLoader cl = A.class.getClassLoader();
        resource = cl.getResourceAsStream("nested");        
        System.out.println("5: cl nested=" + resource);

        resource = cl.getResourceAsStream("/com/example/nested");
        System.out.println("6: cl /com/example/nested=" + resource);
        resource = cl.getResourceAsStream("com/example/nested");
        System.out.println("7: cl com/example/nested=" + resource);

        resource = cl.getResourceAsStream("top");
        System.out.println("8: cl top=" + resource);

        resource = cl.getResourceAsStream("/top");
        System.out.println("9: cl /top=" + resource);
    }

}

The output from the program is:

1: A.class nested=java.io.BufferedInputStream@19821f
2: A.class /com/example/nested=java.io.BufferedInputStream@addbf1
3: A.class top=null
4: A.class /top=java.io.BufferedInputStream@42e816
5: cl nested=null
6: cl /com/example/nested=null
7: cl com/example/nested=java.io.BufferedInputStream@9304b1
8: cl top=java.io.BufferedInputStream@190d11
9: cl /top=null

Mostly things do what you'd expect. Case-3 fails because class relative resolving is with respect to the Class, so "top" means "/com/example/top", but "/top" means what it says.

Case-5 fails because classloader relative resolving is with respect to the classloader. But, unexpectedly Case-6 also fails: one might expect "/com/example/nested" to resolve properly. To access a nested resource through the classloader you need to use Case-7, i.e. the nested path is relative to the root of the classloader. Likewise Case-9 fails, but Case-8 passes.

Remember: for java.lang.Class, getResourceAsStream() does delegate to the classloader:

     public InputStream getResourceAsStream(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResourceAsStream(name);
        }
        return cl.getResourceAsStream(name);
    }

so it is the behavior of resolveName() that is important.

Finally, since it is the behavior of the classloader that loaded the class that essentially controls getResourceAsStream(), and the classloader is often a custom loader, then the resource-loading rules may be even more complex. e.g. for Web-Applications, load from WEB-INF/classes or WEB-INF/lib in the context of the web application, but not from other web-applications which are isolated. Also, well-behaved classloaders delegate to parents, so that duplicateed resources in the classpath may not be accessible using this mechanism.


Just for completeness, there has recently been a question on the Jython mailinglist where one of the answers referred to this thread.

The question was how to call a Python script that is contained in a .jar file from within Jython, the suggested answer is as follows (with "InputStream" as explained in one of the answers above:

PythonInterpreter.execfile(InputStream)

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

Python, Pandas : write content of DataFrame into text File Saving response from Requests to file How to while loop until the end of a file in Python without checking for empty line? Getting "java.nio.file.AccessDeniedException" when trying to write to a folder How do I add a resources folder to my Java project in Eclipse Read and write a String from text file Python Pandas: How to read only first n rows of CSV files in? Open files in 'rt' and 'wt' modes How to write to a file without overwriting current contents? Write objects into file with Node.js

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