2009-07-27 112 views
3

我面对的是代码,试图从那里为类本身的.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() 

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

编辑:为了澄清,假设我们知道这是部署在这样一种方式,MyClass.class总是会从磁盘上的.class文件读取的应用程序中使用,而资源将出现在同一个目录。

+0

发现此相关的问题:http://stackoverflow.com/questions/778187/getting-directory-path-to-class-file-containing-main 其接受的答案使用基本上是我建议[的getResource (“MyClass.class”)。getPath()] ...但它并不直接回答这是唯一的还是最好的方法。 – Jonik 2009-07-27 14:45:23

回答

2

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

一类可能是:

  • 完全在内存
  • 从一个jar文件

加载在网络连接

  • 加载创造了你能习惯的URL创建这个课程本身,如果从file://开始,那么你可以得到其余的......但它不适用于所有类。

  • +0

    是的,我认为这几乎是我的同事在提出替代方案时所表达的意思......但是当*知道该类将始终从磁盘上的文件加载时,*有*场景 - 因此,如果是这种情况,我在问题中提出的最清洁的方式是什么?感谢关于检查URL开始的提示! – Jonik 2009-07-27 14:30:49

    +0

    是的,如果您添加了对文件协议的检查,那么您在那里看到的是对我最干净的方式。 – 2009-07-27 14:46:50

    2

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

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

    正如早些时候公布,类本身可以远程加载或在地方有没有一个正确的“路径”(例如,从一个jar文件)

    1

    我与你的同事是Java类加载是不同意旨在处理这个用例。 Sun Facelets使用了一种类似的策略,假设URL可以映射到文件,但并不漂亮。我同意Jon的评论,即您的getResource解决方案在部署假设的情况下可能是最干净的。由于您问是否唯一的方法,我还会提供getClass()。getProtectionDomain()。getCodeSource()。getLocation(),它应该是类加载器实际加载您的类的URL(您需要追加你的类的包的子目录)。这种策略也有相同的URL-to-File假设,所以在这方面没有更好的办法。我不能想到其他的一般解决方案。

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

    3

    我知道这个主题很旧,但它是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); 
        } 
    } 
    
    相关问题