【问题标题】:How to read file from JAR as file如何从 JAR 中读取文件作为文件
【发布时间】:2016-07-20 21:59:38
【问题描述】:

我已经创建了可执行的jar文件,文件在resources文件夹下

    Example.jar
    |
    |__src
    |  |
    |  Main.class
    |
    File1.txt

我们如何将 File1.txt 读取为文件, 我试过下面的代码

ClassLoader classLoader =Main.class.getClassLoader();
File file= new File(classLoader.getResource("File1.txt").getFile());(without slash)

File file= new File(classLoader.getResource("/File1.txt").getFile());(with slash)

用斜线我得到空指针异常 和 没有斜杠我得到的文件名或目录名不正确

【问题讨论】:

  • 使用绝对路径而不是相对路径更容易

标签: java file classloader iostream


【解决方案1】:

您不需要“文件”实例来读取文件的内容,正如其他人回答的那样,只需使用 Stream 或 URL。 注意使用类加载器时路径是绝对路径:

 Main.class.getClassLoader().getResourceAsStream("fileAtRoot.txt")

等价于

 Main.class.getResourceAsStream("/fileAtRoot.txt")

如果你真的想要这个文件,它在任何情况下都不起作用:如果它是一个文件,你可以得到它,但是当它在 JAR 中时,没有要打开的文件,它只能在 eclipse 中工作,或者如果您在类路径中放置一个文件夹而不是 jar。

这是一个例子:

免责声明:这是一个反模式,请勿实际使用它

public class SOResourceLoad {

  public static void main (String[] args) {
    new SOResourceLoad().run();
  }

  private void run () {
    try {
      URL resource = getClass().getResource("SOResourceLoad.class");
      System.out.println( resource );
      System.out.println( resource.toURI() );
      System.out.println( new File(resource.toURI()) );
    } catch (URISyntaxException e) {
      e.printStackTrace();
    }

  }

}

Eclipse 的结果

file:/D:/opt/workspace/examples/target/classes/pdem/*/SOResourceLoad.class
file:/D:/opt/workspace/examples/target/classes/pdem/*/SOResourceLoad.class
   D:\opt\workspace\examples\target\classes\pdem\*\SOResourceLoad.class

jar 文件的结果:

jar:file:/D:/opt/sodist.jar!/pdem/*/SOResourceLoad.class
jar:file:/D:/opt/sodist.jar!/pdem/*/SOResourceLoad.class
Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierarchical
    at java.io.File.<init>(File.java:418)
    at pdem.*.SOResourceLoad.run(SOResourceLoad.java:25)
    at pdem.*.SOResourceLoad.main(SOResourceLoad.java:17)

stacktrace 告诉我们执行 jar 文件时无法获取 File。

【讨论】:

    【解决方案2】:

    首先,你需要检查你的类加载器,然后加载文件:

    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    if (cl == null) {
        cl = Class.class.getClassLoader();
    }
    cl.getResourceAsStream("File1.txt");
    

    【讨论】:

      【解决方案3】:
      getClass().getResourceAsStream("File1.txt") 
      

      但是,通常您将资源存储在项目内的资源目录和/或 jar 根目录下。所以我会稍微改变结构,将资源目录放在项目的根目录下以及 jar 的目标结构下,然后将 File1.txt 放在那里。所以,新的加载命令应该是这样的:

      getClass().getResourceAsStream("resources/File1.txt")
      

      【讨论】:

        最近更新 更多