使用 Maven 的可执行 jar 中资源文件的相对路径问题
Issue with relative paths of resources files in an executable jar using Maven
我想制作一个 jar 文件来查找任务标签之间的相似之处。为此,我使用了 2 java 个 WordNet 词典库:JWNL-1.4-rc3
和 JWI-2.3.3
。我还在 myProject
的 resources
文件夹中放置了 JWNL 库初始化所需的 properties.xml
文件,以及 WordNet 词典:
src/main/resources/
properties.xml
WordNet-3.0/dict (dict has 24 files inside)
properties.xml
文件的字典路径值为:
<param name="dictionary_path" value="WordNet-3.0\dict"/>
在我的代码中,有如下所示的两个代码片段。
此代码初始化 JWNL 库:
try {
JWNL.initialize(similarities.class.getClassLoader().getResourceAsStream("/properties.xml"));
}
catch (JWNLException e) {
e.printStackTrace();
}
similarities
是我的主class.
这是JWI字典的构造函数:
try {
//String path = similarities.class.getProtectionDomain().getCodeSource().getLocation().getPath();
dict=new Dictionary(this.getClass().getClassLoader().getResource("WordNet-3.0\dict"));
dict.open();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
但是当我导出可执行 jar 并在控制台中 运行 时,出现以下错误:
net.didion.jwnl.JWNLException: Properties file invalid or not found
at net.didion.jwnl.JWNL.initialize(JWNL.java:103)
at com.iteforth.annotationToBPM.similarities.main(similarities.java:576)
Exception in thread "main" java.lang.NullPointerException
at edu.mit.jwi.data.FileProvider.<init>(FileProvider.java:191)
at edu.mit.jwi.data.FileProvider.<init>(FileProvider.java:166)
at edu.mit.jwi.data.FileProvider.<init>(FileProvider.java:148)
at edu.mit.jwi.Dictionary.<init>(Dictionary.java:41)
at com.iteforth.annotationToBPM.similarities.<init>(similarities.java:92)
at com.iteforth.annotationToBPM.similarities.main(similarities.java:627)
我已经打开了我的 jar 文件,我检查了里面有一个 resources
文件夹,里面有 properties.xml
和 WordNet 词典。我也打开了MANIFEST
,我看到class路径是:.
(句号)
我已经阅读了 3 天有关此问题的许多主题,但没有任何内容可以解决我的问题。我将不胜感激任何帮助。
告诉我是否必须发送其他内容,例如 POM.xml
或 properties.xml
文件。
你遇到的错误与属性文件的加载有关,但我认为你会得到另一个与字典加载有关的错误。
对于属性文件:
JWNL.initialize(ClassLoader.getSystemResourceAsStream("properties.xml"));
确保您的文件位于 jar 的根目录下。如果您的源文件位于 src/main/resources 中,那应该是这种情况,因为它是默认的 Maven 配置。如果您的属性文件如您所说位于 jar 中的 "resources" 文件夹中,则变为:
JWNL.initialize(ClassLoader.getSystemResourceAsStream("resources/properties.xml"));
对于词典:
API 不是为读取 jar 中的字典文件而设计的。在第 363 行的 edu.mit.jwi.data.FileProvider 中,您会看到:
File directory = toFile(url);
if (!directory.exists())
throw new IOException("Dictionary directory does not exist: " + directory);
所以你必须把它们放在你的 jar 之外,在文件系统中:
dict = new Dictionary(new File("WordNet-3.0\dict"));
dict.open();
注:
当然,在您的代码中放置一个硬编码的绝对路径并不是一个好主意。
如果你的 jar 总是来自这个目录 运行,你可以将字典目录放在与你的 jar 相同的目录中,并在你的代码中使用相对文件路径访问它,如上(见 How does Java resolve a relative path in new File()?)
或者您可以让用户使用命令行参数配置目录路径 (https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html) or an environnement variable (https://docs.oracle.com/javase/tutorial/essential/environment/env.html)
带有环境变量的示例:
用户定义一个环境变量,例如:
set WORD_NET_DICTIONARY = "C:\WordNet-3.0\Dict"
您可以在您的代码中获取此环境变量并配置您的库:
String wordNetDicDir = System.getenv("WORD_NET_DICTIONARY");
if (wordNetDicDir != null) {
dict = new Dictionary(new File(wordNetDicDir));
dict.open();
} else {
// throw exception or log error
...
}
我想制作一个 jar 文件来查找任务标签之间的相似之处。为此,我使用了 2 java 个 WordNet 词典库:JWNL-1.4-rc3
和 JWI-2.3.3
。我还在 myProject
的 resources
文件夹中放置了 JWNL 库初始化所需的 properties.xml
文件,以及 WordNet 词典:
src/main/resources/
properties.xml
WordNet-3.0/dict (dict has 24 files inside)
properties.xml
文件的字典路径值为:
<param name="dictionary_path" value="WordNet-3.0\dict"/>
在我的代码中,有如下所示的两个代码片段。
此代码初始化 JWNL 库:
try {
JWNL.initialize(similarities.class.getClassLoader().getResourceAsStream("/properties.xml"));
}
catch (JWNLException e) {
e.printStackTrace();
}
similarities
是我的主class.
这是JWI字典的构造函数:
try {
//String path = similarities.class.getProtectionDomain().getCodeSource().getLocation().getPath();
dict=new Dictionary(this.getClass().getClassLoader().getResource("WordNet-3.0\dict"));
dict.open();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
但是当我导出可执行 jar 并在控制台中 运行 时,出现以下错误:
net.didion.jwnl.JWNLException: Properties file invalid or not found
at net.didion.jwnl.JWNL.initialize(JWNL.java:103)
at com.iteforth.annotationToBPM.similarities.main(similarities.java:576)
Exception in thread "main" java.lang.NullPointerException
at edu.mit.jwi.data.FileProvider.<init>(FileProvider.java:191)
at edu.mit.jwi.data.FileProvider.<init>(FileProvider.java:166)
at edu.mit.jwi.data.FileProvider.<init>(FileProvider.java:148)
at edu.mit.jwi.Dictionary.<init>(Dictionary.java:41)
at com.iteforth.annotationToBPM.similarities.<init>(similarities.java:92)
at com.iteforth.annotationToBPM.similarities.main(similarities.java:627)
我已经打开了我的 jar 文件,我检查了里面有一个 resources
文件夹,里面有 properties.xml
和 WordNet 词典。我也打开了MANIFEST
,我看到class路径是:.
(句号)
我已经阅读了 3 天有关此问题的许多主题,但没有任何内容可以解决我的问题。我将不胜感激任何帮助。
告诉我是否必须发送其他内容,例如 POM.xml
或 properties.xml
文件。
你遇到的错误与属性文件的加载有关,但我认为你会得到另一个与字典加载有关的错误。
对于属性文件:
JWNL.initialize(ClassLoader.getSystemResourceAsStream("properties.xml"));
确保您的文件位于 jar 的根目录下。如果您的源文件位于 src/main/resources 中,那应该是这种情况,因为它是默认的 Maven 配置。如果您的属性文件如您所说位于 jar 中的 "resources" 文件夹中,则变为:
JWNL.initialize(ClassLoader.getSystemResourceAsStream("resources/properties.xml"));
对于词典: API 不是为读取 jar 中的字典文件而设计的。在第 363 行的 edu.mit.jwi.data.FileProvider 中,您会看到:
File directory = toFile(url); if (!directory.exists()) throw new IOException("Dictionary directory does not exist: " + directory);
所以你必须把它们放在你的 jar 之外,在文件系统中:
dict = new Dictionary(new File("WordNet-3.0\dict")); dict.open();
注: 当然,在您的代码中放置一个硬编码的绝对路径并不是一个好主意。
如果你的 jar 总是来自这个目录 运行,你可以将字典目录放在与你的 jar 相同的目录中,并在你的代码中使用相对文件路径访问它,如上(见 How does Java resolve a relative path in new File()?)
或者您可以让用户使用命令行参数配置目录路径 (https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html) or an environnement variable (https://docs.oracle.com/javase/tutorial/essential/environment/env.html)
带有环境变量的示例:
用户定义一个环境变量,例如:
set WORD_NET_DICTIONARY = "C:\WordNet-3.0\Dict"
您可以在您的代码中获取此环境变量并配置您的库:
String wordNetDicDir = System.getenv("WORD_NET_DICTIONARY"); if (wordNetDicDir != null) { dict = new Dictionary(new File(wordNetDicDir)); dict.open(); } else { // throw exception or log error ... }