当前位置: 首页 > 知识库问答 >
问题:

从jar内部获取资源文件

壤驷安和
2023-03-14

我需要从应用程序的根内部获得一个资源,当它打包到JAR中时。我的项目是这样的:

ProjectRoot
  resource.txt //want to access from here
  src
    main
       java
         package1
           package2
              package3
                 Main.java
  target
    app.jar
    classes
         resource.txt //works when here
         package1
           package2
              package3
                 Main.class

我使用以下代码:

Path path = Paths.get("resource.txt");

在打包到jar之前运行时,它会发现文件很好(在ProjectRoot内部)。运行jar时,它找不到它,并将此路径转换为target/resource.txt

此代码:

BufferedReader br = new BufferedReader(new InputStreamReader(new Main().getClass().getClassLoader().getResourceAsStream(
                "resource.txt")));

在打包之前运行时,查找目标/classes中的资源。打包后,它声称从.../target/app.jar!/resource.txt中获取资源。

此代码:

BufferedReader br = new BufferedReader(new InputStreamReader(new Main().getClass().getClassLoader().getResourceAsStream(
                    "/resource.txt")));

我想做的只是将资源放在projectroot中,并且能够从jar外部(从IDE运行类文件时)和内部(使用Maven将文件打包到jar文件后)访问它。

编辑:我需要的代码工作的前和后包装。意思是:如果我从IDE内部运行main.java,它将获得资源;如果我将所有内容打包到JAR中并运行JAR,它将获得资源--所有这些都使用相同的代码。

共有1个答案

包翔
2023-03-14

Maven使用标准目录布局。如果您不遵循这个布局,那么插件就不能正确地完成它们的工作。从技术上讲,您可以配置Maven使用不同的目录,但99.999%的情况下这是不必要的。

此布局的一个特点是生产文件进入:

  • /src/main/java
    • 所有*.java文件
      null

    注意:请参阅构建生命周期的介绍,了解更多有关阶段以及由哪个阶段执行哪些插件的信息。这个堆栈溢出问题也可能有用。

    当您从IDE启动应用程序(可能通过exec-maven-plugin)时,target/classes目录将放在类路径中。这意味着从src/main/java编译的所有类和从src/main/resources复制的所有资源都可以通过类路径使用。

    然后,当您将应用程序打包到一个JAR文件中时,target/classes中的所有文件都会添加到结果的JAR文件中(由maven-jar-plugin处理)。这包括从src/main/resources复制的资源。当您使用这个JAR文件启动应用程序时,资源仍然可以通过类路径使用,因为它们嵌入在JAR文件中。

    要使resource.txt在类路径上可用,只需移动:

    <project-dir>/resource.txt
    

    致:

    <project-dir>/src/main/resources/resource.txt.
    

    然后,您可以使用class#getresource/resource.txt作为路径,这样您就可以解决所有问题了。由GetResource返回URL将有所不同,这取决于您是针对target/classes执行还是针对JAR文件执行。

    file:///.../<project-dir>/target/classes/resource.txt
    
    jar:file:///.../<project-dir>/target/projectname-version.jar!/resource.txt
    

    注意:这都假设resource.txt实际上是一个资源,而不是一个外部文件。资源一旦部署到JAR文件中,通常是只读的;如果您需要一个可写文件,那么就由您来为该文件使用一个指定的位置(例如,用户主目录中的一个文件夹)。通常通过java.io.filejava.nio.file.*访问外部文件。请记住,资源与普通文件不是一回事。

    现在,如果您将resource.txt直接放在 下,这对Maven没有任何意义。它不会被复制到target/classes中,也不会最终出现在JAR文件中,这意味着资源在类路径上永远不可用。因此,只是重申一下,所有资源都在src/main/resources下。

    查看java.lang.class#getResource(String)的Javadoc以获得有关路径的更多信息,例如何时使用前导的/以及何时不使用。该链接指向Javadoc for Java12,它包括有关资源和模块的信息(JPMS/Jigsaw模块,而不是Maven模块);如果您不使用模块,您可以忽略文档的这一部分。

 类似资料:
  • 启动jar时,控制台会说找不到文件,也没有加载字体。我怎样才能解决这个问题? 我得到了这个密码:

  • 我想从我的jar中读取一个资源,如下所示: 在Eclipse中运行它时工作良好,但如果我将它导出到一个jar中,然后运行它,就会出现一个IllegalArgumentException: 我真的不知道为什么,但通过一些测试我发现如果我改变 至 然后它的工作方式相反(它在jar中工作,但不能在eclipse中工作)。 我使用的是Eclipse,我的文件所在的文件夹位于类文件夹中。

  • 问题内容: 我在项目的根目录中有一个资源文件夹/程序包,我“不想”加载某个文件。如果我想加载某个文件,我将使用class.getResourceAsStream,我会很好的!我实际上想要做的是在资源文件夹中加载一个“文件夹”,循环访问该文件夹中的文件,并获取每个文件的流,并读取内容…假设在运行时之前未确定文件名… 我该怎么办?有没有一种方法可以获取jar文件中“文件夹”中文件的列表?请注意,带有资

  • 我很难弄清楚这个问题,我几乎什么都试过了。 我希望我的程序从Jar文件中读取两个资源,并且它将在eclipse中运行良好。但是当我从命令提示符运行jar时,它会给出空指针异常。 结构: src/main/java/App。JAVA src/main/resources/properties/application。属性 src/main/resources/spring/applicationCo

  • 我正在尝试将资源csv文件传递到我的Sprint Boot应用程序使用的jar中。尽管方法获取的资源参数=ReactiveWebContext资源[src/main/Resources/file.csv],但我总是得到该文件不存在的响应 > 在我的项目中,文件位于src/main/resources/file中。csv 正在应用中。属性,我定义: 在config类中: 在内部jar:Config类

  • 问题内容: 我正在尝试从作为桌面应用程序运行的单独jar中访问jar文件中的XML文件。我可以获取所需文件的URL,但是当我将其传递给FileReader(作为字符串)时,我得到了FileNotFoundException,上面写着“文件名,目录名或卷标语法不正确”。 作为参考,我毫不费力地从同一个jar中读取图像资源,并将URL传递给ImageIcon构造函数。这似乎表明我用来获取URL的方法是