英文:
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:
<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>
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("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);
}
}
}
}
The file is loaded with:
File file = new File(getClass().getClassLoader().getResource("template.txt").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'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 "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)
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't care if it comes from a real file or a jar
InputStream is = getClass().getClassLoader().getResourceAsStream("fix.cfg");
InputStreamReader reader = new InputStreamReader(is);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论