问题
My code runs inside a JAR file and I need to get the full path of that file. For example, my JAR is called example.jar and is located at D:\example\ So I need to get "D:\example\example.jar" by some code inside that jar. I have tried many methods to get that path, but none of them worked correctly.
One of them is
getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()
Many people say that this works for them, but it returns "rsrc:./" for me.
I have searched after that and I noticed that my MANIFEST.MF contains this:
Manifest-Version: 1.0
Rsrc-Class-Path: ./
Class-Path: .
Rsrc-Main-Class: Example
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
I don't know what that means, but if I remove that Rsrc stuff and replace the other things with it, it says the jar is broken. I think this is the reason why it doesn't work. Does anybody know what this means?
PS: I'm running my JAR using a BAT file.
回答1:
I stumbled over this problem too and leave my investigations here for people who ask themselves in the future what the rsrc
means.
I'm using Eclipse Mars 1 and try to export my project as a runnable JAR. There I can choose the library handling and decide between:
- Extract required libraries into generated JAR
- Package required libraries into generated JAR
- Copy required libraries into a sub-folder next to the generated JAR
The line to be tested is
System.out.println(MyClass.class.getProtectionDomain().getCodeSource().getLocation());
the JAR file's name is MyJar.jar (which will be put on desktop), Project's name and folder is MyProject.
Results:
file:/C:/Users/admin/Desktop/MyJar.jar
rsrc:./
file:/C:/Users/admin/Desktop/MyJar.jar
- <means running in Eclipse>
file:/C:/Development/workspace/MyProject/target/classes/
I wrote a convinience method for that:
public class SystemUtils {
/**
* Let no one instanciate this class.
*/
private SystemUtils() {}
/**
* If the current JVM was started from within a JAR file.
* @return <code>Boolean.TRUE</code> if it is, <code>Boolean.FALSE</code> if it is not, <code>null</code> if unknown.
*/
public static Boolean executedFromWithinJar() {
Boolean withinJar = null;
try {
String location = SystemUtils.class.getProtectionDomain().getCodeSource().getLocation().toString();
if (location.startsWith("rsrc:")
|| location.endsWith(".jar") && !new File(location.substring(location.indexOf(':') + 1)).isDirectory())
withinJar = Boolean.TRUE;
else
withinJar = Boolean.FALSE;
}
catch (Exception ex) {/* value is still null */}
return withinJar;
}
}
回答2:
Based on your comments, it appears your real question is how to copy files from inside your application .jar. You can do that with something like this:
String jarEntry = "/files/data.txt";
Path destination = Paths.get(
System.getProperty("user.home"), "Downloads", "data.txt");
try (InputStream stream = getClass().getResourceAsStream(jarEntry)) {
Files.copy(stream, destination);
}
Class.getResource and Class.getResourceAsStream read data from the classpath, usually as an entry in a .jar file that is on the classpath, such as your own application’s .jar file.
A file embedded in the classpath is normally called an application resource or just “resource” for short. Resources are always specified using the forward slash (/
) as a directory separator, on all platforms, even Windows.
If you are not sure what string you should pass to getResource or getResourceAsStream, examine the contents of your .jar file.
回答3:
package com.example;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
public class HomeJar {
public static void main(String[] args) throws IOException {
URL u = HomeJar.class.getProtectionDomain().getCodeSource().getLocation();
File f = new File(u.getPath().toString());
if (!f.isFile()) {
throw new RuntimeException("'" + u + "' isn't a jar");
}
try (JarInputStream jis = new JarInputStream(new BufferedInputStream(new FileInputStream(f)))) {
JarEntry je = jis.getNextJarEntry();
while (je != null) {
System.out.println(je.getName());
je = jis.getNextJarEntry();
}
}
}
}
回答4:
I just have created a new workspace and moved every project into it and everything works fine now, I think it was a bug or something...Thank you all for your help!
来源:https://stackoverflow.com/questions/37902711/getting-the-path-of-a-running-jar-file-returns-rsrc