Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read a file from jar in Java?

Tags:

java

file-io

jar

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?

like image 680
kandarp Avatar asked Jul 30 '10 08:07

kandarp


People also ask

Can I read code from JAR file?

Hi, Jar files are archive files that contains of a lot of different java classes (files). You can use winzip/winrar to open the jar files and you can see those java classes in jar files. Typically you can use a Java decompiler to decompile the class file and look into the source code.

How do I extract a JAR file?

JAR files work just like ZIP files. You can use any archive program to extract them. On Windows, you can Install WinRAR 7-Zip, or WinZIP. Macs have their own built-in archive program called Archive Utility.


2 Answers

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.

like image 134
Mnementh Avatar answered Sep 28 '22 02:09

Mnementh


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.

like image 29
simontuffs Avatar answered Sep 28 '22 02:09

simontuffs