我的代码在一个JAR文件中运行,比如foo.jar,我需要知道,在代码中,运行的foo.jar在哪个文件夹中。
所以,如果FOO .jar在C:\FOO\中,无论我当前的工作目录是什么,我都想获得这个路径。
我的代码在一个JAR文件中运行,比如foo.jar,我需要知道,在代码中,运行的foo.jar在哪个文件夹中。
所以,如果FOO .jar在C:\FOO\中,无论我当前的工作目录是什么,我都想获得这个路径。
当前回答
令人沮丧的是,当您在Eclipse中进行开发时,MyClass.class.getProtectionDomain(). getcodesource (). getlocation()返回/bin目录,这很好,但当您将其编译到jar时,该路径包括/myjarname.jar部分,这为您提供了非法的文件名。
为了让代码既能在ide中工作,又能编译到jar中,我使用了下面这段代码:
URL applicationRootPathURL = getClass().getProtectionDomain().getCodeSource().getLocation();
File applicationRootPath = new File(applicationRootPathURL.getPath());
File myFile;
if(applicationRootPath.isDirectory()){
myFile = new File(applicationRootPath, "filename");
}
else{
myFile = new File(applicationRootPath.getParentFile(), "filename");
}
其他回答
我已经尝试了上面的几种解决方案,但是对于在Eclipse中使用“打包外部库”导出可运行jar的情况(可能是特殊情况),没有一个产生正确的结果。出于某种原因,所有基于ProtectionDomain的解决方案在这种情况下都将导致null。
通过结合上面的一些解决方案,我成功地实现了以下工作代码:
String surroundingJar = null;
// gets the path to the jar file if it exists; or the "bin" directory if calling from Eclipse
String jarDir = new File(ClassLoader.getSystemClassLoader().getResource(".").getPath()).getAbsolutePath();
// gets the "bin" directory if calling from eclipse or the name of the .jar file alone (without its path)
String jarFileFromSys = System.getProperty("java.class.path").split(";")[0];
// If both are equal that means it is running from an IDE like Eclipse
if (jarFileFromSys.equals(jarDir))
{
System.out.println("RUNNING FROM IDE!");
// The path to the jar is the "bin" directory in that case because there is no actual .jar file.
surroundingJar = jarDir;
}
else
{
// Combining the path and the name of the .jar file to achieve the final result
surroundingJar = jarDir + jarFileFromSys.substring(1);
}
System.out.println("JAR File: " + surroundingJar);
对我来说最好的解决方案:
String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
这应该可以解决空格和特殊字符的问题。
这段代码用于识别程序是否在JAR文件或IDE中执行:
private static boolean isRunningOverJar() {
try {
String pathJar = Application.class.getResource(Application.class.getSimpleName() + ".class").getFile();
if (pathJar.toLowerCase().contains(".jar")) {
return true;
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
如果我需要获得JAR文件的Windows完整路径,我使用这个方法:
private static String getPathJar() {
try {
final URI jarUriPath =
Application.class.getResource(Application.class.getSimpleName() + ".class").toURI();
String jarStringPath = jarUriPath.toString().replace("jar:", "");
String jarCleanPath = Paths.get(new URI(jarStringPath)).toString();
if (jarCleanPath.toLowerCase().contains(".jar")) {
return jarCleanPath.substring(0, jarCleanPath.lastIndexOf(".jar") + 4);
} else {
return null;
}
} catch (Exception e) {
log.error("Error getting JAR path.", e);
return null;
}
}
我的完整代码使用CommandLineRunner实现与Spring Boot应用程序一起工作,以确保应用程序总是在控制台视图中执行(在JAR文件名中错误地双击),我使用下面的代码:
@SpringBootApplication
public class Application implements CommandLineRunner {
public static void main(String[] args) throws IOException {
Console console = System.console();
if (console == null && !GraphicsEnvironment.isHeadless() && isRunningOverJar()) {
Runtime.getRuntime().exec(new String[]{"cmd", "/c", "start", "cmd", "/k",
"java -jar \"" + getPathJar() + "\""});
} else {
SpringApplication.run(Application.class, args);
}
}
@Override
public void run(String... args) {
/*
Additional code here...
*/
}
private static boolean isRunningOverJar() {
try {
String pathJar = Application.class.getResource(Application.class.getSimpleName() + ".class").getFile();
if (pathJar.toLowerCase().contains(".jar")) {
return true;
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
private static String getPathJar() {
try {
final URI jarUriPath =
Application.class.getResource(Application.class.getSimpleName() + ".class").toURI();
String jarStringPath = jarUriPath.toString().replace("jar:", "");
String jarCleanPath = Paths.get(new URI(jarStringPath)).toString();
if (jarCleanPath.toLowerCase().contains(".jar")) {
return jarCleanPath.substring(0, jarCleanPath.lastIndexOf(".jar") + 4);
} else {
return null;
}
} catch (Exception e) {
return null;
}
}
}
实际上,这里有一个更好的版本-如果文件夹名中有空格,旧的版本就会失败。
private String getJarFolder() {
// get name and path
String name = getClass().getName().replace('.', '/');
name = getClass().getResource("/" + name + ".class").toString();
// remove junk
name = name.substring(0, name.indexOf(".jar"));
name = name.substring(name.lastIndexOf(':')-1, name.lastIndexOf('/')+1).replace('%', ' ');
// remove escape characters
String s = "";
for (int k=0; k<name.length(); k++) {
s += name.charAt(k);
if (name.charAt(k) == ' ') k += 2;
}
// replace '/' with system separator char
return s.replace('/', File.separatorChar);
}
至于applet失败的原因,您通常无法访问本地文件。我不太了解JWS,但要处理本地文件,可能无法下载该应用程序。
如果你从Gnome桌面环境(不是任何脚本或终端)点击运行jar,上面所选的答案是不工作的。
相反,我认为下面的解决方案在任何地方都适用:
try {
return URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");
} catch (UnsupportedEncodingException e) {
return "";
}