使用 Maven 的可执行 jar 中资源文件的相对路径问题

Issue with relative paths of resources files in an executable jar using Maven

我想制作一个 jar 文件来查找任务标签之间的相似之处。为此,我使用了 2 java 个 WordNet 词典库:JWNL-1.4-rc3JWI-2.3.3。我还在 myProjectresources 文件夹中放置了 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.xmlproperties.xml 文件。

你遇到的错误与属性文件的加载有关,但我认为你会得到另一个与字典加载有关的错误。

  1. 对于属性文件:

    JWNL.initialize(ClassLoader.getSystemResourceAsStream("properties.xml"));
    

确保您的文件位于 jar 的根目录下。如果您的源文件位于 src/main/resources 中,那应该是这种情况,因为它是默认的 Maven 配置。如果您的属性文件如您所说位于 jar 中的 "resources" 文件夹中,则变为:

JWNL.initialize(ClassLoader.getSystemResourceAsStream("resources/properties.xml"));
  1. 对于词典: 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
       ...
    }