【问题标题】:getClassLoader().getResource("Configuration.xml").getPath() does not work inside a jargetClassLoader().getResource("Configuration.xml").getPath() 在 jar 中不起作用
【发布时间】:2015-08-27 15:19:13
【问题描述】:

我创建了一个基于 maven 的 java 项目,其中包含资源目录 (src/java/resources),其中包含一些 xml 文件,maven 将它们复制到 target/classes/resources 中(target/classes 是我的类路径)。

要知道 xml 文件的内容,我使用:

new FileInputStream(Main.class.getClassLoader().getResource("Configuration.xml").getPath());

Main.class.getClassLoader().getResource("Configuration.xml").getPath() 为我提供了 xml 的完整路径:“c:\project...\Configuration.xml”。

这在 intellij 上效果很好。

但是当我将项目编译并打包成一个 jar 文件时,我得到:

Exception in thread "main" java.io.FileNotFoundException: 
file:\C:\project\target\project-12.50.14-SNAPSHOT-jar-with-dependencies
.jar!\Configuration.xml 

(The filename, directory name, or volume label syntax is incorrect)

那是因为路径:\C:\project\target\project-12.50.14-SNAPSHOT-jar-with-dependencies .jar!\Configuration.xml 不能作为 FileInputStream() 的参数。

我无法将 getResource() 替换为 getResourceAsStream()。

我需要一种方法来调整我的 jar 和资源,使其像在 intellij 上一样工作。 我还在运行时更改了 xml 资源文件的内容,因此将它们保存在 jar 中是另一个问题。

谁能给我一个解决方案,让我不必更改我的代码,而是更改我的资源目录结构,或更改类路径,或者其他可以让我的代码正常工作的东西? 谢谢。

【问题讨论】:

  • “我无法将 getResource() 替换为 getResourceAsStream()” - 为什么不呢?从根本上说,您不能使用FileInputStream 来获取嵌入在jar 文件中的文件。您应该适当地重构您的代码,以便您可以使用getResourceAsStream
  • 为什么需要使用 FileInputStream?
  • 我无法替换它,因为这不是我的代码。我只能消费这个类而不能改变它。此外 - 我还在运行时更改了 connection.xml,所以我更喜欢这个文件将位于 jar 之外(如 intellij "target/class/connection.xml" 上的目录)
  • 啊,我明白了——这是一个关于构建/打包的问题,​​而不是关于编程的问题。
  • 看起来 Intellij 将包含 Configuration.xml 的目录放在类路径中,但是当您将项目打包到 jar 中时,类路径中只有 jar。您需要提取 Configuration.xml 并确保它的目录在运行时类路径上的 jar 之前。

标签: java xml maven intellij-idea maven-resources-plugin


【解决方案1】:

更新:改为使用File,而不是Path

这是因为getResource 返回一个URL,并不是所有的url 都是磁盘上的文件,即可以转换为Path。正如javadoc 所说“如果 [path part] 不存在,则返回 [...] 一个空字符串”。

如果它绝对必须FileFileInputStream,因为您无法更改的其他代码需要它,则将内容复制到临时文件:

File file = File.createTempFile("Configuration", ".xml");
try {
    try {InputStream in = Main.class.getClassLoader().getResourceAsStream("Configuration.xml")) {
        Files.copy(in, file.toPath()); // requires Java 7
    }
    // use file here, or:
    try {FileInputStream in = new FileInputStream(file)) {
        // use file stream here
    }
} finally {
    file.delete();
}

如果资源是文件,上述代码可以优化为不复制,但由于这仅适用于开发模式,生产模式始终是 Jar 并且总是需要副本,使用 copy in开发模式有助于测试代码。

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    • 2017-08-01
    • 1970-01-01
    • 2017-04-01
    • 2011-04-17
    • 2010-10-12
    相关资源
    最近更新 更多