Maven问题:访问资源文件时的问题

huangapple go评论83阅读模式
英文:

Maven Issue With Accessing Resource File

问题

我正在尝试使用Maven构建一个JAR文件,该文件将在运行时从文件系统加载文件。在使用以下命令编译后,我遇到了一个加载文件的问题:

mvn clean package

pom.xml:

<build>
    <resources>
        <resource>
            <filtering>true</filtering>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>App</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>7</source>
                <target>7</target>
            </configuration>
        </plugin>
    </plugins>
</build>

我的主类是:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class App {
    public static void main(String[] args) throws IOException {
        App app = new App();
        app.printTestFile();
    }

    public void printTestFile() throws IOException {
        File file = new File(getClass().getClassLoader().getResource("template.txt").getFile());
        System.out.println("File is in " + file.getAbsolutePath());
        printFile(file);
    }

    private static void printFile(File file) throws IOException {
        try (FileReader reader = new FileReader(file);
             BufferedReader br = new BufferedReader(reader)) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }
    }
}

该文件是这样加载的:

File file = new File(getClass().getClassLoader().getResource("template.txt").getFile());

项目结构如下:

│   pom.xml
└───src
    ├───main
    │   ├───java
    │   │       App.java
    │   └───resources
    │           template.txt
    └───test
        └───java

在IntelliJ中运行时的结果是:

File is in C:\Users\user\Documents\Git\maven-scratch\target\classes\template.txt
This is the test file's content.

然而,当纯粹使用Maven运行时,如下所示:

mvn clean package
java -jar target\maven-scratch-1.0-SNAPSHOT.jar

会输出以下错误:

File is in C:\Users\user\Documents\Git\maven-scratch\file:\C:\Users\user\Documents\Git\maven-scratch\target\maven-scratch-1.0-SNAPSHOT.jar!\template.txt
Exception in thread "main" java.io.FileNotFoundException: file:\C:\Users\user\Documents\Git\maven-scratch\target\maven-scratch-1.0-SNAPSHOT.jar!\template.txt (The filena
me, directory name, or volume label syntax is incorrect)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(Unknown Source)
        at java.io.FileInputStream.<init>(Unknown Source)
        at java.io.FileReader.<init>(Unknown Source)
        at App.printFile(App.java:19)
        at App.printTestFile(App.java:15)
        at App.main(App.java:9)

最令我困惑的是,试图加载的文件路径如下:

C:\Users\user\Documents\Git\maven-scratch\file:\C:\Users\user\Documents\Git\maven-scratch\target\maven-scratch-1.0-SNAPSHOT.jar!\template.txt

但在IntelliJ中,路径是:

C:\Users\user\Documents\Git\maven-scratch\target\classes\template.txt

有没有一种简单的方法可以从Maven的资源文件夹中使用文件,并在使用Maven打包为JAR后,也能够从目标目录中读取该文件?

英文:

I am trying to use Maven to build a JAR file that will load files from the file system during runtime. I am having an issue with loading the file after compiling it with

 mvn clean package

pom.xml:

&lt;build&gt;
    &lt;resources&gt;
        &lt;resource&gt;
            &lt;filtering&gt;true&lt;/filtering&gt;
            &lt;directory&gt;src/main/resources&lt;/directory&gt;
        &lt;/resource&gt;
    &lt;/resources&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-jar-plugin&lt;/artifactId&gt;
            &lt;version&gt;3.1.0&lt;/version&gt;
            &lt;configuration&gt;
                &lt;archive&gt;
                    &lt;manifest&gt;
                        &lt;addClasspath&gt;true&lt;/addClasspath&gt;
                        &lt;classpathPrefix&gt;lib/&lt;/classpathPrefix&gt;
                        &lt;mainClass&gt;App&lt;/mainClass&gt;
                    &lt;/manifest&gt;
                &lt;/archive&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
            &lt;configuration&gt;
                &lt;source&gt;7&lt;/source&gt;
                &lt;target&gt;7&lt;/target&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

My main Class is:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class App {
    public static void main(String[] args) throws IOException {
        App app = new App();
        app.printTestFile();
    }

    public void printTestFile() throws IOException {
        File file = new File(getClass().getClassLoader().getResource(&quot;template.txt&quot;).getFile());
        System.out.println(&quot;File is in &quot; + file.getAbsolutePath());
        printFile(file);
    }

    private static void printFile(File file) throws IOException {
        try (FileReader reader = new FileReader(file);
             BufferedReader br = new BufferedReader(reader)) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }
    }
}

The file is loaded with:

File file = new File(getClass().getClassLoader().getResource(&quot;template.txt&quot;).getFile());

The project structure is:

│   pom.xml
└───src
    ├───main
    │   ├───java
    │   │       App.java
    │   └───resources
    │           template.txt
    └───test
        └───java

When run with IntelliJ the result is:

File is in C:\Users\user\Documents\Git\maven-scratch\target\classes\template.txt
This is the test file&#39;s content.

However, the issue comes when run purely with Maven like:

mvn clean package
java -jar target\maven-scratch-1.0-SNAPSHOT.jar

Outputs the error:

File is in C:\Users\user\Documents\Git\maven-scratch\file:\C:\Users\user\Documents\Git\maven-scratch\target\maven-scratch-1.0-SNAPSHOT.jar!\template.txt
Exception in thread &quot;main&quot; java.io.FileNotFoundException: file:\C:\Users\user\Documents\Git\maven-scratch\target\maven-scratch-1.0-SNAPSHOT.jar!\template.txt (The filena
me, directory name, or volume label syntax is incorrect)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(Unknown Source)
        at java.io.FileInputStream.&lt;init&gt;(Unknown Source)
        at java.io.FileReader.&lt;init&gt;(Unknown Source)
        at App.printFile(App.java:19)
        at App.printTestFile(App.java:15)
        at App.main(App.java:9)

The thing that puzzles me the most is that the file that's trying to be loaded has the path:

C:\Users\user\Documents\Git\maven-scratch\file:\C:\Users\user\Documents\Git\maven-scratch\target\maven-scratch-1.0-SNAPSHOT.jar!\template.txt

... whether with IntelliJ the path is:

C:\Users\user\Documents\Git\maven-scratch\target\classes\template.txt

Is there an easy way to use a file from Maven's resources folder and after packaging into a JAR with Maven to also be able to read the file from the target directory?

答案1

得分: 0

使用Maven Assembly插件生成目标jar文件可能会帮助您解决这个问题。
maven assembly

英文:

Use maven assembly plugin to generate the target jar may help you to solve this issue.
maven assembly

答案2

得分: 0

The JAR construction is fine (easily verified by loading it into a zip file viewer).

IntelliJ的类路径是本地文件系统 - 它正在加载一个真实文件 ./target/classes/template.txt

命令行类路径正在寻找相同的东西 在JAR文件内部 (maven-scratch-1.0-SNAPSHOT.jar!\template.txt)。这实际上不是一个文件本身,而是位于JAR文件内部的一些字节。基本上,它不能被 FileReader 读取,因为 FileReader 寻找的是一个名为 maven-scratch-1.0-SNAPSHOT.jar!\template.txt 的文件。

    // getResourceAsStream不关心它是来自真实文件还是JAR文件
    InputStream is = getClass().getClassLoader().getResourceAsStream("fix.cfg");
    InputStreamReader reader = new InputStreamReader(is);
英文:

The JAR construction is fine (easily verified by loading it into a zip file viewer).

IntelliJ's classpath is the local filesystem - it is loading a real file ./target/classes/template.txt

Commandline classpath is looking for the same thing inside the JAR file (maven-scratch-1.0-SNAPSHOT.jar!\template.txt). This is not an actual file itself, it is some bytes inside the JAR file. Basically it can't be read by FileReader which is looking for a file literally named maven-scratch-1.0-SNAPSHOT.jar!\template.txt

    // getResourceAsStream doesn&#39;t care if it comes from a real file or a jar
    InputStream is = getClass().getClassLoader().getResourceAsStream(&quot;fix.cfg&quot;);
    InputStreamReader reader = new InputStreamReader(is);

huangapple
  • 本文由 发表于 2020年7月29日 20:27:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/63153578.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定