java 获取给定类文件的目录路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1188400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting the path to the directory of a given class file
提问by Jonik
I was confronted with code which tries to read some configuration files from the same directory where the .class file for the class itself is:
我遇到了试图从类本身的 .class 文件所在的同一目录读取一些配置文件的代码:
File[] configFiles = new File(
this.getClass().getResource(".").getPath()).listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".xml");
}
});
Apparently this works in some cases (when running the code inside Resin, perhaps), but for me, running Tomcat, it simply fails with NPE, because getClass().getResource(".")returns null.
显然这在某些情况下有效(可能在 Resin 中运行代码时),但对我来说,运行 Tomcat,它只是因为 NPE 而失败,因为getClass().getResource(".")返回null.
A colleague suggested creating another config file containing a list of all the ".xml" config files (which indeed would work here as it stays quite static), and that you shouldn't really try to do something like this in Java.
一位同事建议创建另一个配置文件,其中包含所有“.xml”配置文件的列表(这确实可以在这里工作,因为它保持相当静态),并且您不应该真正尝试在 Java 中执行此类操作。
Still, I'm wondering if there is somenice way, which works universally, for getting the path to the directory where a given .class file is located? I guess you could get it from the path of the .class file itself like this:
不过,我想知道是否有一些很好的方法,它普遍适用,用于获取给定 .class 文件所在目录的路径?我想你可以像这样从 .class 文件本身的路径中得到它:
new File(this.getClass().getResource("MyClass.class").getPath()).getParent()
... but is this the only / cleanest way?
...但这是唯一/最干净的方法吗?
Edit: To clarify, assume we knowthis is used in an application deployed in such a way that MyClass.class will always be read from a .class file on disk, and the resources will be there in that same directory.
编辑:为了澄清,假设我们知道这在以这样的方式部署的应用程序中使用,即 MyClass.class 将始终从磁盘上的 .class 文件中读取,并且资源将在同一目录中。
回答by LadyCailin
I know this thread is old, but it's the top result in Google searches, and there were no satisfactory answers on here, for me. Here's some code I wrote, which works great for me. Of course there's the caveat that it may not have been loaded from disk, but it accounts for that, and returns null in that case. This works fine for finding the "container," that is, the root location of a class, be it a jar, or a folder. This may not suit your needs directly. If not, feel free to rip out the portions of the code that you do need.
我知道这个帖子很旧,但它是 Google 搜索中的最高结果,对我来说,这里没有令人满意的答案。这是我写的一些代码,它对我很有用。当然有一个警告,它可能没有从磁盘加载,但它说明了这一点,并在这种情况下返回 null。这适用于查找“容器”,即类的根位置,无论是 jar 还是文件夹。这可能无法直接满足您的需求。如果没有,请随意撕掉您确实需要的代码部分。
/**
* Returns the container url for this class. This varies based on whether or
* not the class files are in a zip/jar or not, so this method standardizes
* that. The method may return null, if the class is a dynamically generated
* class (perhaps with asm, or a proxy class)
*
* @param c The class to find the container for
* @return
*/
public static String GetClassContainer(Class c) {
if (c == null) {
throw new NullPointerException("The Class passed to this method may not be null");
}
try {
while(c.isMemberClass() || c.isAnonymousClass()){
c = c.getEnclosingClass(); //Get the actual enclosing file
}
if (c.getProtectionDomain().getCodeSource() == null) {
//This is a proxy or other dynamically generated class, and has no physical container,
//so just return null.
return null;
}
String packageRoot;
try {
//This is the full path to THIS file, but we need to get the package root.
String thisClass = c.getResource(c.getSimpleName() + ".class").toString();
packageRoot = StringUtils.replaceLast(thisClass, Pattern.quote(c.getName().replaceAll("\.", "/") + ".class"), "");
if(packageRoot.endsWith("!/")){
packageRoot = StringUtils.replaceLast(packageRoot, "!/", "");
}
} catch (Exception e) {
//Hmm, ok, try this then
packageRoot = c.getProtectionDomain().getCodeSource().getLocation().toString();
}
packageRoot = URLDecoder.decode(packageRoot, "UTF-8");
return packageRoot;
} catch (Exception e) {
throw new RuntimeException("While interrogating " + c.getName() + ", an unexpected exception was thrown.", e);
}
}
回答by Jon Skeet
What makes you assume that there's a class file on disk in its own directory?
是什么让您假设磁盘上有一个类文件在其自己的目录中?
A class could be:
一个类可以是:
- Created entirely in memory
- Loaded from a network connection
- Loaded from a jar file
- 完全在内存中创建
- 从网络连接加载
- 从 jar 文件加载
You can get the URL used to create the class itself, and if that starts with file://then you could get the rest... but it won't work for all classes.
您可以获得用于创建类本身的 URL,如果以 开头,file://那么您可以获得其余的......但它不适用于所有类。
回答by Dan Fleet
If the resource is in the same folder as a .class file, it should be accessible via the classpath and can be loaded via getResourceAsStream directly.
如果资源与 .class 文件在同一个文件夹中,它应该可以通过类路径访问,并且可以直接通过 getResourceAsStream 加载。
this.getClass().getResourceAsStream( "filename.xml" )
As is posted earlier, classes themselves can be loaded remotely or in places where there's not a proper "path" (e.g. from a jarfile)
正如之前发布的那样,类本身可以远程加载或在没有正确“路径”的地方(例如来自 jarfile)
回答by Brett Kail
I agree with your colleague that Java class loading was not designed to handle this use case. Sun Facelets uses a similar strategy of assuming URLs can be mapped to Files, and it's not pretty. I agree with Jon's comment that your getResource solution is probably the cleanest given your deployment assumptions. Since you asked if it was the only way, I'll also offer getClass().getProtectionDomain().getCodeSource().getLocation(), which should be the URL that the class loader actually loaded your class from (you would need to append the subdirectories for your class' package). This strategy also has the same URL-to-File assumptions, so it's no better in that regard. I can think of no other general solutions.
我同意你的同事的意见,即 Java 类加载不是为了处理这个用例而设计的。Sun Facelets 使用类似的策略,假设 URL 可以映射到文件,但它并不漂亮。我同意 Jon 的评论,即鉴于您的部署假设,您的 getResource 解决方案可能是最干净的。既然你问这是否是唯一的方法,我也会提供 getClass().getProtectionDomain().getCodeSource().getLocation(),它应该是类加载器实际加载你的类的 URL(你需要为您的类的包附加子目录)。此策略也具有相同的 URL-to-File 假设,因此在这方面并没有更好。我想不出其他通用的解决方案。
Note that getResource returns an encoded URL, which means that you should not use getPath() directly. In particular, spaces will causes issues, though this might not be an issue if you have control over your environment. Consider using new File(URL.toURI()).
请注意,getResource 返回一个编码的 URL,这意味着您不应直接使用 getPath()。特别是,空间会导致问题,但如果您可以控制环境,这可能不是问题。考虑使用 new File(URL.toURI())。
回答by Ivan Dubrov
I think, you may be interested in PathMatchingResourcePatternResolverfrom the Spring Framework. You can use it directly in your code for navigating the configuration files or you can look for the implementation here.
我想,您可能对Spring Framework中的PathMatchingResourcePatternResolver感兴趣。您可以直接在代码中使用它来导航配置文件,也可以在此处查找实现。

