代码之家  ›  专栏  ›  技术社区  ›  Jonik

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

  •  3
  • Jonik  · 技术社区  · 16 年前

    我遇到一段代码,该代码试图从类本身的.class文件所在的目录中读取一些配置文件:

    File[] configFiles = new File(
        this.getClass().getResource(".").getPath()).listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".xml");
            }
    });
    

    getClass().getResource(".") null .

    一位同事建议创建另一个配置文件,其中包含所有“.xml”配置文件的列表(它在这里确实可以工作,因为它保持相当静态),并且您不应该在Java中尝试这样做。

    一些 这是一个很好的方法,它可以通用地获取给定.class文件所在目录的路径?我想您可以从.class文件本身的路径获得它,如下所示:

    new File(this.getClass().getResource("MyClass.class").getPath()).getParent()
    

    ... 但这是唯一/最干净的方法吗?

    :为了澄清,假设我们 知道 在部署的应用程序中使用这种方法,MyClass.class将始终从磁盘上的.class文件中读取,并且资源将位于同一目录中。

    5 回复  |  直到 16 年前
        1
  •  3
  •   LadyCailin    12 年前

    /**
     * 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);
        }
    }
    
        2
  •  2
  •   Jon Skeet    16 年前

    是什么让您假设磁盘上有一个类文件在它自己的目录中?

    • 从网络连接加载
    • 从jar文件加载

    您可以获取用于创建类本身的URL,如果以 file:// 然后你可以得到剩下的。。。但这并不适用于所有班级。

        3
  •  2
  •   Dan Fleet    16 年前

    如果资源与.class文件位于同一文件夹中,则应可通过类路径访问该资源,并可通过getResourceAsStream直接加载该资源。

    this.getClass().getResourceAsStream( "filename.xml" )
    

        4
  •  1
  •   Brett Kail    16 年前

    我同意你的同事的观点,Java类加载不是为了处理这个用例而设计的。Sun Facelets使用了一种类似的策略,假设URL可以映射到文件,但这并不漂亮。我同意Jon的评论,即考虑到您的部署假设,您的getResource解决方案可能是最干净的。既然您询问这是否是唯一的方法,我还将提供getClass().getProtectionDomain().getCodeSource().getLocation(),它应该是类加载器实际从中加载类的URL(您需要为类的包附加子目录)。这个策略也有相同的URL到文件的假设,所以在这方面没有更好的选择。我想不出其他通用的解决方案。

    请注意,getResource返回一个编码的URL,这意味着您不应该直接使用getPath()。特别是,空间会导致问题,尽管如果您可以控制环境,这可能不是问题。考虑使用新文件(URL.TURIO())。

        5
  •  0
  •   Ivan Dubrov    16 年前

    我想,你可能对 PathMatchingResourcePatternResolver 来自Spring框架。您可以在代码中直接使用它来导航配置文件,也可以查找实现 here