获取给定类文件的目录的路径

时间:2009-07-27 14:15:40

标签: java file filepath

我遇到的代码试图从类本身的.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磁盘,资源将存在于同一目录中。

5 个答案:

答案 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)

是什么让你认为磁盘上有一个类文件在自己的目录中?

课程可以是:

  • 完全在内存中创建
  • 从网络连接加载
  • 从jar文件加载

您可以获取用于创建类本身的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

相关问题