java jar - 如何指定应将资源保存在何处?

java jar - how do I specify where resources should be saved?

这是我当前的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>hu.elte.inf</groupId>
    <artifactId>ThesisMVN</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
            <plugin>
                <!-- Build an executable JAR -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>main/Main</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.javatuples</groupId>
            <artifactId>javatuples</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>
</project>

我需要维护我的资源文件夹(及其子文件夹)的结构,因为目前将它们从资源文件夹中取出,所以我的游戏无法启动,因为它找不到所有纹理。
项目内的资源结构

jar-ed 资源结构(注意 jar 中只有一个 effects 文件夹,它将图像放在 class 文件旁边)

这是我当前加载图片的方式

public class ResourceLoader {
    public static Image getResource(String path){
        Image img=null;
        try{
           img = ImageIO.read(new File(path));
        }
        catch(IOException e) {
            System.err.println("File not found("+path+')');
            e.printStackTrace();
        }
        return img;
    }
}

传递给 getResource 的 path 是从我设置所有图像路径的枚举中获取的,如下所示:

...
BULLET("src/main/resources/bullet.png"),
BULLET_GREY("src/main/resources/bullet_grey.png"),
...
AOE_SLOW("src/main/resources/effects/aoeSlow.png"),
AOE_DISARM("src/main/resources/effects/aoeDisarm.png"),
...

我想我应该删除 src/main/resources 前缀,但是一旦项目被破坏,我就只能访问图像。

这可能是我的设置中不可靠的部分,但我目前正在将每个加载的图像存储在名为 GameStateData 的 class 中。每当我需要创建一个新的 Sprite 时,我只是从那里获取已经加载的图像,所以我只需要在启动游戏时加载每个图像一次。

I need the structure of my resources folder (and its subfolders) maintained

维护的。资源文件夹中的每个文件 和目录 都已按照标准目录布局的要求直接复制到 jar 中。

问题出在您的设置上:在 'dev time' 时,您似乎试图从 resources/items/someItem.png 加载,但当您的应用程序出现问题时,这不起作用。有两种明显的方式可以发生这种情况;

你不明白原因

您正在尝试使用 new FileInputStreamnew File,或者试图将这些 作为文件 加载。这行不通,也行不通,对目录结构进行再多的调整也无法使其发挥作用。在 java 中,file 表示 file - jarfile 中的 png 条目本身不是文件。

加载此类资源的方式始终是这种策略:

  1. 选择一个 class 即 'source location' - 例如,您正在寻找的资源将是 where-ever JVM 找到了这个 class 文件。通常,您可以在整个应用程序中选择任何 class;这仅在您使用模块化 class 加载系统时才有意义。如果您不知道那是什么意思,那么您就没有使用这些。

  2. 调用 MyContextClass.class.getResource(resourceKey) 获得一个 URL 对象,然后你可以将它传递给任何 API 允许你这样做的对象(还有很多 APIs 做,特别是包括 swing 自己的 ImageIcon)。或者,使用 try (var in = MyContextClass.class.getResourceAsStream(resourceKey) { /* use resource here */ } - 如果所讨论的 API 没有采用 URL 的重载但确实有采用 InputStream 的重载,则可以使用此方法。直接看内容也可以用这个

  3. resourceKey 有两种口味。 "foo/bar.png" 解析相对于 package 上下文 class 所在的路径。如果你有 package com.foo; public class Bar {} 那么在部署的某个地方有 com/foo/Bar.class。例如,在 jar 文件中,或在 bin 目录中。如果您随后写入 Bar.class.getResource("baz/quux.png"),并且 Bar.class 位于该 jar 文件中,那么系统将在同一个 jar 文件中查找 com/foo/baz/quux.png。或者,包括一个前导斜杠:"/foo/bar.png" 会在同一个 jar 中查找,但对于 foo/bar.png.

  4. 这就是您要做的全部。构建系统和 IDEs 确保您将图像准确地放在现在的位置(在 resources 文件夹中),您 包含 resources 在您的部署密钥中(出于同样的原因,您在 src/main/java/com/foo/MyApp.class 中拥有 java 源文件,并且您不包括 srcmainjava在您完全限定的 class 名称中。它只是 com.foo.MyApp,而不是 main.java.com.foo.MyAppresources 不再是它的一部分,就像 java 是它的一部分一样您的 class 个名称。如果它不起作用,则说明它们配置错误。

您的设置不可靠

您可能一直在偷偷摸摸,例如使用插件系统,您可以自己直接在文件系统上检查某些文件,-或-通过 ContextClass.class.getResource 加载,或者您一直在搞乱 IDE 的 maven 插件识别资源目录的方式,或者您一直在手动设置 IDE 项目(而不是使用其 Maven 集成)并将 src/main 标记为源目录(而不是 src/main/javasrc/main/resources) .设置坏了;解决这个问题(不要 'fix' 它试图保持 resources 左右)。