我遇到的代码试图从类本身的.class文件所在的同一目录中读取一些配置文件:
File[] configFiles = new File(
this.getClass().getResource(".").getPath()).listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".xml");
}
});
显然这在某些情况下有效(当在Resin中运行代码时),但对我来说,运行Tomcat时,它只是因NPE而失败,因为getClass().getResource(".")
返回null
。
一位同事建议创建另一个配置文件,其中包含所有“.xml”配置文件的列表(这确实可以在这里工作,因为它保持非常静态),并且你不应该真的尝试在Java中做这样的事情。
仍然,我想知道是否有一些这种普遍适用的方法,用于获取给定.class文件所在目录的路径?我想你可以从.class文件本身的路径中得到它:
new File(this.getClass().getResource("MyClass.class").getPath()).getParent()
......但这是唯一/最干净的方式吗?
编辑:为了澄清,假设我们知道这是在部署的应用程序中使用的,以便始终从.class文件中读取MyClass.class磁盘,资源将存在于同一目录中。
答案 0 :(得分:3)
我知道这个帖子已经老了,但这是谷歌搜索的最高结果,对我来说这里没有令人满意的答案。这是我写的一些代码,对我来说很有用。当然有一点需要注意,它可能没有从磁盘加载,但它解释了这一点,并在这种情况下返回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);
}
}
答案 1 :(得分:2)
是什么让你认为磁盘上有一个类文件在自己的目录中?
课程可以是:
您可以获取用于创建类本身的URL,如果以file://
开头,则可以获得其余的...但它不适用于所有类。
答案 2 :(得分:2)
如果资源与.class文件位于同一文件夹中,则应该可以通过类路径访问它,并且可以通过getResourceAsStream直接加载。
this.getClass().getResourceAsStream( "filename.xml" )
如前所述,类本身可以远程加载,也可以在没有正确“路径”的地方加载(例如从jar文件中)
答案 3 :(得分:1)
我同意您的同事Java类加载不是为处理此用例而设计的。 Sun Facelets使用了一种类似的策略,假设URL可以映射到Files,而且它并不漂亮。我同意Jon的意见,即鉴于您的部署假设,您的getResource解决方案可能是最干净的。既然你问这是否是唯一的方法,我还会提供getClass()。getProtectionDomain()。getCodeSource()。getLocation(),它应该是类加载器实际加载你的类的URL(你需要附加您的类'包的子目录。此策略也具有相同的URL-to-File假设,因此在这方面并不是更好。我想不出其他一般的解决方案。
请注意,getResource返回一个编码的URL,这意味着您不应该直接使用getPath()。特别是,空格会导致问题,但如果您可以控制您的环境,这可能不是问题。考虑使用新文件(URL.toURI())。
答案 4 :(得分:0)
我想,您可能对Spring Framework中的PathMatchingResourcePatternResolver感兴趣。您可以直接在代码中使用它来导航配置文件,也可以查找实现here。