【问题标题】:Using resource files in an executeable jar [duplicate]使用可执行 jar 中的资源文件 [重复]
【发布时间】:2019-03-22 13:03:37
【问题描述】:

我正在尝试熟悉 maven 并为此创建了一个测试项目。我创建了一个简单的类,它只打印一些东西,从 .txt 文件中读取。我的主要课程如下所示:

public class HelloWorld {
    public static void main(String[] args) throws IOException {
        String filePath = HelloWorld.class.getClassLoader().getResource("test.txt").getFile();

        BufferedReader br = new BufferedReader(new FileReader(filePath));
        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        br.close();
    }
}

我创建了一个资源文件夹,将其标记为资源根目录,修改了资源模式并从我的项目中打包了一个可执行的 jar。我的项目结构如下:

Quickstart
├───.idea
├───src
│   ├───main
│   │   ├───java
│   │   │   └───de
│   │   │       └───mb
│   │   │           └───hello
|   |   |               └───HelloWorld.java
│   │   └───resources
|   |       └───test.txt

现在我的问题是,当我尝试执行我的 jar 时,我收到以下错误:

Exception in thread "main" java.io.FileNotFoundException:   
file:\C:\Users\mb\IdeaProjects\Quickstart\target\Quickstart-1.
0-SNAPSHOT.jar!\test.txt (The filename, directory name, or volume label syntax is incorrect)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at java.io.FileReader.<init>(FileReader.java:58)
    at de.mb.hello.HelloWorld.main(HelloWorld.java:15)

我想问题是,.txt 文件在 .jar 中,但我应该如何声明路径以使其工作?我已经尝试使用不同的方法让我的资源路径无济于事并修改了我的 pom.xml:

<project>
    ...
    <build>
        <resources>
            <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.txt</include>
            </includes>
            </resource>
        </resources>
        ...
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.2.0</version>
                    <configuration>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <manifestEntries>
                            <Main-Class>de.mb.hello.HelloWorld</Main-Class>
                        </manifestEntries>
                        </transformer>
                    </transformers>
                    </configuration>
                    <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

更新:按照建议,我将代码更改为使用 getResourceAsStream() 而不是 getResource() 并且它可以正常工作,如下所示:

public static void main(String[] args) {
    try {
        InputStream in = HelloWorld.class.getClassLoader().getResourceAsStream("test.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        try {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } finally {
            in.close();
            br.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

【问题讨论】:

    标签: java maven intellij-idea maven-shade-plugin


    【解决方案1】:

    你的 jar 文件中打包的资源不是一个 File,而是一个 zip 文件中的一系列字节。它必须被处理有一个字节流。

    使用 getResourceAsStream(...) 而不是 getResource(...) 来获取 InputStream 而不是 File 并使用 InputStreamReader 而不是 FileReader 读取内容。

    不要忘记在 finally 块中或使用 try-with-resources 关闭资源。

    类似的东西:

    public class HelloWorld {
        public static void main(String[] args) throws IOException {
            try(BufferedReader br = new BufferedReader(new InputStreamReader(HelloWorld.class.getClassLoader().getResourceAsStream("test.txt")))) {
              String line;
              while ((line = br.readLine()) != null) {
                  System.out.println(line);
              }
           }
        }
    }
    

    【讨论】:

    • 感谢这项工作,也感谢您的详细解释!
    猜你喜欢
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-10
    • 1970-01-01
    • 2018-04-16
    • 2011-06-27
    相关资源
    最近更新 更多