我的代码在一个JAR文件中运行,比如说foo.jar,我需要在代码中知道运行foo.jar的文件夹。
所以,如果foo.jar在C:\FOO\
中,无论我目前的工作目录是什么,我都希望得到这条路径。
答案 0 :(得分:496)
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
.toURI()).getPath();
将“MyClass”替换为您班级的名称。
显然,如果您的类是从非文件位置加载的,那么这会很奇怪。
答案 1 :(得分:186)
最适合我的解决方案:
String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
这应解决空格和特殊字符的问题。
答案 2 :(得分:143)
要获得给定File
的{{1}},有两个步骤:
Class
转换为Class
URL
转换为URL
理解这两个步骤非常重要,而不是将它们混为一谈。
获得File
后,如果您需要,可以致电File
获取包含文件夹。
getParentFile
至Class
正如其他答案中所讨论的,有两种主要方法可以找到与URL
相关的URL
。
Class
URL url = Bar.class.getProtectionDomain().getCodeSource().getLocation();
两者都有利有弊。
URL url = Bar.class.getResource(Bar.class.getSimpleName() + ".class");
方法产生类的基本位置(例如,包含JAR文件)。但是,Java运行时的安全策略可能在调用getProtectionDomain
时抛出SecurityException
,因此如果您的应用程序需要在各种环境中运行,最好在所有环境中进行测试。 / p>
getProtectionDomain()
方法生成类的完整URL资源路径,您需要从中执行其他字符串操作。它可能是getResource
路径,但在OSGi框架内执行时,它也可能是file:
或甚至更像jar:file:
的更糟糕的东西。相反,即使在OSGi中,bundleresource://346.fwk2106232034:4/foo/Bar.class
方法也能正确生成getProtectionDomain
网址。
请注意,当类位于JAR文件中时,我的测试中file:
和getResource("")
都失败了;两个调用都返回null。所以我推荐上面显示的#2调用,因为它似乎更安全。
getResource(".")
至URL
无论哪种方式,一旦您拥有File
,下一步就会转换为URL
。这是它自己的挑战;有关详细信息,请参阅Kohsuke Kawaguchi's blog post about it,但简而言之,只要网址格式正确,您就可以使用File
。
最后,我会高度劝阻使用new File(url.toURI())
。网址的某些字符,尤其是URLDecoder
和:
,不是有效的网址编码字符。来自URLDecoder Javadoc:
假设编码字符串中的所有字符都是以下之一:“a”到“z”,“A”到“Z”,“0”到“9”和“ - ”,“_ “,”。“和”*“。允许使用字符“%”,但会将其解释为特殊转义序列的开头。
...
这种解码器可以通过两种方式处理非法字符串。它可能会单独留下非法字符,也可能会抛出IllegalArgumentException。解码器采用哪种方法留待实施。
在实践中,/
通常不会将URLDecoder
投掷为上述威胁。如果您的文件路径的空格编码为IllegalArgumentException
,则此方法似乎可行。但是,如果您的文件路径包含其他非字母数字字符,例如%20
,则+
会损坏您的文件路径。
要实现这些步骤,您可能会使用以下方法:
URLDecoder
您可以在SciJava Common库中找到这些方法:
答案 3 :(得分:49)
您也可以使用:
CodeSource codeSource = YourMainClass.class.getProtectionDomain().getCodeSource();
File jarFile = new File(codeSource.getLocation().toURI().getPath());
String jarDir = jarFile.getParentFile().getPath();
答案 4 :(得分:24)
使用ClassLoader.getResource()查找当前类的URL。
例如:
package foo;
public class Test
{
public static void main(String[] args)
{
ClassLoader loader = Test.class.getClassLoader();
System.out.println(loader.getResource("foo/Test.class"));
}
}
(此示例取自a similar question。)
要查找目录,您需要手动拆分URL。有关jar URL的格式,请参阅JarClassLoader tutorial。
答案 5 :(得分:17)
我很惊讶地发现最近没有人建议使用Path
。下面是一个引用:“ Path
类包括各种方法,可用于获取有关路径的信息,访问路径元素,将路径转换为其他形式,或提取路径的一部分< / EM>“
因此,一个好的选择是将Path
客观化为:
Path path = Paths.get(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());
答案 6 :(得分:14)
唯一适用于Linux,Mac和Windows的解决方案:
public static String getJarContainingFolder(Class aclass) throws Exception {
CodeSource codeSource = aclass.getProtectionDomain().getCodeSource();
File jarFile;
if (codeSource.getLocation() != null) {
jarFile = new File(codeSource.getLocation().toURI());
}
else {
String path = aclass.getResource(aclass.getSimpleName() + ".class").getPath();
String jarFilePath = path.substring(path.indexOf(":") + 1, path.indexOf("!"));
jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
jarFile = new File(jarFilePath);
}
return jarFile.getParentFile().getAbsolutePath();
}
答案 7 :(得分:8)
这是对其他评论的升级,对于
的具体细节我似乎不完整使用.jar文件外的相对“文件夹”(在jar中也是如此) 位置):
String path =
YourMainClassName.class.getProtectionDomain().
getCodeSource().getLocation().getPath();
path =
URLDecoder.decode(
path,
"UTF-8");
BufferedImage img =
ImageIO.read(
new File((
new File(path).getParentFile().getPath()) +
File.separator +
"folder" +
File.separator +
"yourfile.jpg"));
答案 8 :(得分:8)
我遇到了同样的问题,我就这样解决了:
File currentJavaJarFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String currentJavaJarFilePath = currentJavaJarFile.getAbsolutePath();
String currentRootDirectoryPath = currentJavaJarFilePath.replace(currentJavaJarFile.getName(), "");
我希望我对你有所帮助。
答案 9 :(得分:6)
为了获得运行jar文件的路径,我研究了上述解决方案并尝试了所有存在一些差异的方法。如果这些代码在Eclipse IDE中运行,那么它们都应该能够找到包含指定类的文件路径,并打开或创建带有找到路径的指定文件。
但是这很棘手,当直接或通过命令行运行runnable jar文件时,它将失败,因为从上面的方法获取的jar文件的路径将在jar文件中给出内部路径,即它总是给出了一条路径
rsrc:project-name(也许我应该说它是主类文件的包名 - 指示的类)
我无法将rsrc:...路径转换为外部路径,即在Eclipse IDE外部运行jar文件时无法获取jar文件的路径。
获取在Eclipse IDE外部运行jar文件的路径的唯一可能方法是
System.getProperty("java.class.path")
这段代码行可能会返回正在运行的jar文件的生存路径(包括文件名)(注意返回路径不是工作目录),因为java文件和一些人说它会返回路径同一目录中的所有类文件,但作为我的测试,如果在同一目录中包含许多jar文件,它只返回运行jar的路径(关于多路径问题确实发生在Eclipse中)。
答案 10 :(得分:4)
如果您通过从Gnome桌面环境(而不是从任何脚本或终端)点击它来运行您的jar,则上面选择的答案无效。
相反,我喜欢以下解决方案无处不在:
try {
return URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");
} catch (UnsupportedEncodingException e) {
return "";
}
答案 11 :(得分:3)
实际上这里是一个更好的版本 - 如果文件夹名称中有空格,则旧版本会失败。
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了解不多,但是处理本地文件可能无法下载应用程序。?
答案 12 :(得分:3)
其他答案似乎指向代码源,它是Jar文件位置,不是目录。
使用
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile();
答案 13 :(得分:3)
最简单的解决方案是在运行jar时将路径作为参数传递。
您可以使用shell脚本(Windows中的.bat,其他任何地方的.sh)自动执行此操作:
java -jar my-jar.jar .
我使用.
传递当前的工作目录。
<强>更新强>
您可能希望将jar文件粘贴在子目录中,以免用户意外点击它。您的代码还应检查以确保已提供命令行参数,并在缺少参数时提供良好的错误消息。
答案 14 :(得分:3)
jarLocation
可能会带有file:\
或jar:file\
这样的前缀,可以使用String#substring()
删除。
URL jarLocationUrl = MyClass.class.getProtectionDomain().getCodeSource().getLocation();
String jarLocation = new File(jarLocationUrl.toString()).getParent();
答案 15 :(得分:2)
我尝试使用
获取jar运行路径String folder = MyClassName.class.getProtectionDomain().getCodeSource().getLocation().getPath();
c:\ app&gt; java -jar application.jar
在Windows上的“ c:\ app ”文件夹中运行名为“application.jar”的jar应用程序,String变量“folder”的值为“ \ c: \ app \ application.jar “我在测试路径正确性方面遇到了问题
File test = new File(folder);
if(file.isDirectory() && file.canRead()) { //always false }
所以我试着将“test”定义为:
String fold= new File(folder).getParentFile().getPath()
File test = new File(fold);
以正确的格式获取路径,例如“ c:\ app ”而不是“ \ c:\ app \ application.jar ”,我发现它有效
答案 16 :(得分:2)
如果您确实在寻找一种简单的方法来获取JAR所在的文件夹,则应实施此格式的解决方案 它比您将要查找的要容易(很难找到并且不再支持许多解决方案,许多其他解决方案提供了文件的路径,而不是实际目录),并且已证明可以在1.12版上使用。>
new File(".").getCanonicalPath()
从其他答案中收集输入也很简单:
String localPath=new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParentFile().getPath()+"\\";
两者都将返回以下格式的字符串:
"C:\Users\User\Desktop\Folder\"
简洁明了。
答案 17 :(得分:2)
public static String dir() throws URISyntaxException
{
URI path=Main.class.getProtectionDomain().getCodeSource().getLocation().toURI();
String name= Main.class.getPackage().getName()+".jar";
String path2 = path.getRawPath();
path2=path2.substring(1);
if (path2.contains(".jar"))
{
path2=path2.replace(name, "");
}
return path2;}
在Windows上运行良好
答案 18 :(得分:2)
String path = getClass().getResource("").getPath();
路径始终引用jar文件中的资源。
答案 19 :(得分:1)
令人沮丧的是,当您在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");
}
答案 20 :(得分:1)
对其他人不太确定,但在我的情况下,它不能与“Runnable jar”一起工作,我通过修复代码从phchen2回答和另一个来自此链接的工作:How to get the path of a running JAR file? 代码:
String path=new java.io.File(Server.class.getProtectionDomain()
.getCodeSource()
.getLocation()
.getPath())
.getAbsolutePath();
path=path.substring(0, path.lastIndexOf("."));
path=path+System.getProperty("java.class.path");
答案 21 :(得分:1)
在那里尝试了几种解决方案,但是对于(可能是特殊的)情况(在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);
答案 22 :(得分:0)
以上方法在我的Spring环境中对我不起作用,因为Spring将实际的类着色到一个名为BOOT-INF的包中,而不是正在运行的文件的实际位置。我找到了另一种通过已授予运行文件的Permissions
对象检索运行文件的方法:
public static Path getEnclosingDirectory() {
return Paths.get(FileUtils.class.getProtectionDomain().getPermissions()
.elements().nextElement().getName()).getParent();
}
答案 23 :(得分:0)
此方法从存档中的代码调用,返回.jar文件所在的文件夹。它应该适用于Windows或Unix。
private String getJarFolder() {
String name = this.getClass().getName().replace('.', '/');
String s = this.getClass().getResource("/" + name + ".class").toString();
s = s.replace('/', File.separatorChar);
s = s.substring(0, s.indexOf(".jar")+4);
s = s.substring(s.lastIndexOf(':')-1);
return s.substring(0, s.lastIndexOf(File.separatorChar)+1);
}
的代码
答案 24 :(得分:0)
提到仅在Windows
中进行检查,但我认为它在其他操作系统[Linux,MacOs,Solaris
]上运行良好:)。
我在同一目录中有 2 .jar
个文件。我希望从一个.jar
文件中启动位于同一目录中的另一个.jar
文件。
问题是,当您从cmd
启动它时,当前目录为system32
。
警告!
;][[;'57f2g34g87-8+9-09!2#@!$%^^&()
或()%&$%^@#
它运作良好。ProcessBuilder
以及以下内容:...
//The class from which i called this was the class `Main`
String path = getBasePathForClass(Main.class);
String applicationPath= new File(path + "application.jar").getAbsolutePath();
System.out.println("Directory Path is : "+applicationPath);
//Your know try catch here
//Mention that sometimes it doesn't work for example with folder `;][[;'57f2g34g87-8+9-09!2#@!$%^^&()`
ProcessBuilder builder = new ProcessBuilder("java", "-jar", applicationPath);
builder.redirectErrorStream(true);
Process process = builder.start();
//...code
getBasePathForClass(Class<?> classs)
:
/**
* Returns the absolute path of the current directory in which the given
* class
* file is.
*
* @param classs
* @return The absolute path of the current directory in which the class
* file is.
* @author GOXR3PLUS[StackOverFlow user] + bachden [StackOverFlow user]
*/
public static final String getBasePathForClass(Class<?> classs) {
// Local variables
File file;
String basePath = "";
boolean failed = false;
// Let's give a first try
try {
file = new File(classs.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
if (file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {
basePath = file.getParent();
} else {
basePath = file.getPath();
}
} catch (URISyntaxException ex) {
failed = true;
Logger.getLogger(classs.getName()).log(Level.WARNING,
"Cannot firgue out base path for class with way (1): ", ex);
}
// The above failed?
if (failed) {
try {
file = new File(classs.getClassLoader().getResource("").toURI().getPath());
basePath = file.getAbsolutePath();
// the below is for testing purposes...
// starts with File.separator?
// String l = local.replaceFirst("[" + File.separator +
// "/\\\\]", "")
} catch (URISyntaxException ex) {
Logger.getLogger(classs.getName()).log(Level.WARNING,
"Cannot firgue out base path for class with way (2): ", ex);
}
}
// fix to run inside eclipse
if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")
|| basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {
basePath = basePath.substring(0, basePath.length() - 4);
}
// fix to run inside netbeans
if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {
basePath = basePath.substring(0, basePath.length() - 14);
}
// end fix
if (!basePath.endsWith(File.separator)) {
basePath = basePath + File.separator;
}
return basePath;
}
答案 25 :(得分:0)
此代码对我有用:
private static String getJarPath() throws IOException, URISyntaxException {
File f = new File(LicensingApp.class.getProtectionDomain().().getLocation().toURI());
String jarPath = f.getCanonicalPath().toString();
String jarDir = jarPath.substring( 0, jarPath.lastIndexOf( File.separator ));
return jarDir;
}
答案 26 :(得分:0)
尝试一下:
String path = new File("").getAbsolutePath();
答案 27 :(得分:0)
此代码对我有用,可以确定该程序是否正在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;
}
}
如果我需要获得Windows JAR文件的完整路径,请使用以下方法:
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;
}
}
}
答案 28 :(得分:-1)
对于一些愚蠢的简单事情,您只需要这一行:
对于 Windows 用户,将“pwd”更改为“cd”
runCommand("pwd");
然后把这个方法扔到类中:
public static String runCommand(String command) {
StringBuilder sb = new StringBuilder();
try {
ProcessBuilder pb = new ProcessBuilder(command);
final Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
sb.append(br.read());
while ((line= br.readLine()) != null) sb.append(line).append("\n");
}
catch (IOException e) {e.printStackTrace();}
return sb.toString();
}
答案 29 :(得分:-1)
我有另一种获取类的String位置的方法。
URL path = Thread.currentThread().getContextClassLoader().getResource("");
Path p = Paths.get(path.toURI());
String location = p.toString();
输出字符串的格式为
C:\Users\Administrator\new Workspace\...
处理空格和其他字符,格式为file:/
。所以会更容易使用。
答案 30 :(得分:-1)
getProtectionDomain
方法有时可能不起作用,例如当你必须为某些核心java类找到jar时(例如在IBM JDK中我的StringBuilder
类),但是后续工作无缝地进行:
public static void main(String[] args) {
System.out.println(findSource(MyClass.class));
// OR
System.out.println(findSource(String.class));
}
public static String findSource(Class<?> clazz) {
String resourceToSearch = '/' + clazz.getName().replace(".", "/") + ".class";
java.net.URL location = clazz.getResource(resourceToSearch);
String sourcePath = location.getPath();
// Optional, Remove junk
return sourcePath.replace("file:", "").replace("!" + resourceToSearch, "");
}
答案 31 :(得分:-1)
我在Java 7中编写,在Windows 7中使用Oracle的运行时进行测试,在Ubuntu中使用开源运行时进行测试。这适用于那些系统:
任何正在运行的jar文件的父目录的路径(假设调用此代码的类是jar存档本身的直接子代):
try {
fooDir = new File(this.getClass().getClassLoader().getResource("").toURI());
} catch (URISyntaxException e) {
//may be sloppy, but don't really need anything here
}
fooDirPath = fooDir.toString(); // converts abstract (absolute) path to a String
所以,foo.jar的路径是:
fooPath = fooDirPath + File.separator + "foo.jar";
同样,这未在任何Mac或较旧的Windows上进行测试