Marcus Mathioudakis
Marcus Mathioudakis

Reputation: 837

How to access contents of a jar using resource path?

My problem is the following: I am trying to access a class file in a Jar. I have a jar "dumb.jar" located in package "com.msgxsd". The jar is on the classpath, and If I try and do

InputStream is = this.getClass().getClassLoader()
            .getResourceAsStream("com/msgxsd/dumb.jar");

then I get an input stream for the jar without a problem.

The problem arises when I try and get an input stream (or a URL) for the file inside the jar. All the jar contains (apart from the manifest obviously) is the file "DummyClass1.class".

I have tried all of the following:

InputStream is = this.getClass().getClassLoader() .getResourceAsStream("DummyClass1.class");

InputStream is = this.getClass().getClassLoader() .getResourceAsStream("dumb.jar!/DummyClass1.class");

But the input stream returned is always null. I have also tried

URL url = this.getClass().getResource("DummyClass1.class");
URL url = this.getClass().getResource("dumb.jar!/DummyClass1.class");

But the URL returned is null.

I have already looked at every single one of the questions relating to accessing a file within a Jar, but the proposed solutions (as seen above) do not work for me.

All I want is to be able to get either an InputStream (or ideally a URL) for the "DummyClass1.class" inside the jar, so that I can the somehow construct a File instance.

Any suggestions would be much appreciated.

Upvotes: 2

Views: 642

Answers (5)

rxg
rxg

Reputation: 3982

The simplest thing for you to do is to move your jar so that it is included directly in the classpath, or change your classpath to also include "com/msgxsd" as a top-level entry. In either of these cases DummyClass will be loaded by the standard ClassLoader and you can simply do getResourceAsStream("DummyClass1.class") as you have already suggested.

If changing your classpath in this way is not possible then you need to create a JarInputStream as suggested by @Micky above or in this more complete answer.

Upvotes: 1

Micky Ray
Micky Ray

Reputation: 11

What I would do is use a JarInputStream to access the contents of the jar file directly. Then iterate through the JarEntry collection until you find the file you are looking for and read it from the stream. Something like this:

JarInputStream jarIn = new JarInputStream(this.getClass().getClassLoader() .getResourceAsStream("com/msgxsd/dumb.jar"));  
JarEntry entry = jarIn.getNextJarEntry();

Now read the file using the jarIn read method.

Upvotes: 1

tibtof
tibtof

Reputation: 7957

Try

is = this.getClass().getClassLoader().getResourceAsStream("com/msgxsd/dumb.jar!/DummyClass1.class")

Upvotes: 1

petrumo
petrumo

Reputation: 1116

Try

InputStream is = this.getClass().getClassLoader().getResourceAsStream("dumb.jar/DummyClass1.class"); 

maybe specify the DummyClass1.class location inside the jar

Upvotes: 2

mprivat
mprivat

Reputation: 21902

Try this (sorry if there are typos, I'm just typing the code off the top of my head without trying it):

int index = path.indexOf('!');
if (index == -1) return url.openStream();
String jarPath = path.substring(0, index);
File jarFile = new File(new URL(jarPath).toURI());

if (!jarFile.exists()) return null;

String filePath = path.substring(index + 1);
if (filePath.startsWith("/")) {
    filePath = filePath.substring(1);
}

JarFile jar = new JarFile(jarFile);
return jar.getInputStream(jar.getJarEntry(filePath));

Upvotes: 1

Related Questions