【问题标题】:My executable jar can't open resource files when I run it outside of netbeans当我在 netbeans 之外运行时,我的可执行 jar 无法打开资源文件
【发布时间】:2025-12-26 19:35:18
【问题描述】:

在这里的第一篇文章,我希望我已经充分形成了这个问题。我的项目在作为项目在 netbeans 内部运行时在类路径上找到资源文件,但是当我在 netbeans 外部运行 jar 时,它找不到资源(我已经检查过,是的,它们被放入 jar 中。 )

我已经尝试了我的代码的 .getResource() 和 .getResourceAsStream() 版本。它们在作为 Maven 项目在 netbeans 内部运行时都成功了,但是当我删除 jar 并在 netbeans 外部运行它时找不到这些资源。

这是我的代码的 sn-p,以及我添加资源的 pom 文件中的 sn-p。当在 netbeans 中作为项目运行时,这一切都有效,但当我在其他地方运行 jar 时就不行。找不到资源。

... ...

    String wholeFile = "";
    try {

       BufferedReader objReader = new BufferedReader(
                new java.io.InputStreamReader(
                        getClass().getResourceAsStream( sqlFileName ) 
            )
        );

        StringBuilder sb = new StringBuilder();
        String strCurrentLine;
        while ( (strCurrentLine = objReader.readLine()) != null ) {
            sb.append( strCurrentLine );
            sb.append( System.getProperty("line.separator") );
        }
        wholeFile = sb.toString();

...或者,最好是...

        wholeFile = java.nio.file.Files.readString(
            java.nio.file.Paths.get( 
                getClass().getClassLoader().getResource( sqlFileName ).toURI()
            ) 
        );


    // Split that file into individual create
    // table strings contained in the file.

    // Slit on two newlines.
        String newLine = System.getProperty("line.separator");
        String[] tables = wholeFile.split( newLine + newLine );

... ...

这是我添加到 pom 中的内容。但这只有在 netbeans 中运行时才能解决。为什么?我在这里的 Maven 设置缺少什么?在 netbeans 之外...可执行 jar 不会像在 netbeans 中运行时那样找到这些资源文件。

提前致谢。我希望我的问题很清楚。

<resources>
    <resource>
        <directory>src/my-resources</directory>
            <includes>
                <include>**/*.txt</include>
                <include>**/*.jpg</include>
            </includes>
    </resource>
</resources>

【问题讨论】:

  • 比较一下 sqlFileName 的值和 *.jar 的内容会很有趣。
  • "CreateTables.txt" "BasicInserts.txt" ... 并且在 jar 中,它们位于根级别。
  • "/CreateTables.txt" 也可以工作......但在 netbeans 之外......都不工作。
  • 在 jar ... com 和 META-INF 以及 CreateTables.txt 和 BasicInserts.txt 内。他们肯定会进入罐子。

标签: java maven netbeans


【解决方案1】:

java.nio.file.Files 无法读取 *.jar 文件的内容,据我所知。您需要通过类加载器作为流访问资源。所以我认为你的第一次尝试应该没问题。

这可能只是路径名的问题。这是一个没有 Maven 的工作示例:

文件 src/de/stefanfrings/Main.java:

package de.stefanfrings;

import java.io.InputStream;
import java.util.*;

public class Main
{
    public static void main(String[] args)
    {
        InputStream stream=Main.class.getResourceAsStream("/test.txt");
        Scanner in=new Scanner(stream);
        while (in.hasNextLine())
        {
            System.out.println(in.nextLine());
        }
        in.close();
    }
}

文件src/de/test.txt:

Hello
World

test.jar 的内容:

META-INF/MANIFEST.MF
test.txt
de/stefanfrings/Main.class

输出:

java -jar test.jar
Hello
World

如果我将文件名更改为“../../test.txt”,那么它只能在 IDE 中工作,因为 IDE 从编译器放置其输出的(未压缩)文件夹中执行程序。

尝试在文件名前加上“/”。

【讨论】:

  • 谢谢。你修好了。 Main.class.getResourceAsStream 而不是 getClass().getResourceAsStream 以某种方式改变了一切。
  • 嗯,我写了Main.class,因为我的类是静态的,因此没有getClass() 方法。
  • 我知道,当我使用你的方式时......我很自然地将 GumBDBInsert.class 放在了你的 Main.class 的位置......因为它是我班级的名称。现在......这一切都有效,在netbeans之外也是如此。当我使用 .getClass() 甚至 .getClass().getClassLoader() 变体时,它会失败。使用您的方法,并将其设为 InputStream stream = GumBDBInsert.class.getResourceAsStream( sqlFileName ); ... 一切顺利。似乎无法使用 .getClass() 方法。
  • 好的,作为我的最后评论,感谢 Stefan 向我指出解决方案,当我现在使用 .getClass() 时它确实有效......在远离 netbeans 的可执行 jar 中。它似乎与使用更简单的 InputStream 有关......这是我的最终解决方案。 InputStream 流 = getClass().getResourceAsStream( sqlFileName );类名中没有硬编码,所以这里的解决方案是:使用 InputStream。
【解决方案2】:
            StringBuilder sb = new StringBuilder();
            InputStream stream = getClass().getResourceAsStream( sqlFileName );
            Scanner in=new java.util.Scanner(stream);
            while (in.hasNextLine())
            {
                    //System.out.println(in.nextLine());
                    sb.append( in.nextLine() );
                    sb.append( System.getProperty("line.separator") );
            }
            in.close();
            wholeFile = sb.toString();

非常感谢,已经解决了。在这里只使用直接的 InputStream 有一些不同。您的代码有效。

现在可以工作了,...也在 netbeans 之外。非常感谢!

【讨论】:

  • 使用 Scanner 而不是 BufferedReader 不能解决此问题。 Scanner 在后台使用 BufferedReader。问题出在文件名中。
  • 当然。我在这里使用扫描仪只是为了举例说明如何相同几行代码。
  • 再次感谢您的帮助 Stefan,您为我指明了一个方向,无论出于何种原因,它都为我工作。我现在只是使用 InputStream 继续前进。稍后我可能会使用 BufferedReader 和 Files.readString appraoches 来看看发生了什么。但老实说,我在发布的初始代码中尝试的第一件事是确保我的文件路径以 '/' ... /CreateTables.txt ... 为前缀,但它不起作用。 InputStream 现在可以工作,所以我正在继续前进。再次感谢,它现在可以稳定运行,远离可执行 jar 中的 netbeans。
最近更新 更多