如何构建包含外部文件的 Jar 文件

How to build a Jar file that include external files

我想将资源文件夹中的文本文件包含到 Jar 文件中。这是最小的例子:

import java.io.File;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        main.readFile( "test.txt" );
    }

    public void readFile(String fileName){
        File file = new File( getClass().getResource( fileName ).getPath() );

        try{
            Scanner scanner = new Scanner( file );
            while ( scanner.hasNextLine() ){
                System.out.println( scanner.nextLine() );
            }
        }catch (Exception e){
            System.out.println( e );
        }
    }
}

这是 test.txt 文件中的内容:

hello
world

这是我的项目的样子:

我可以运行 代码成功。我生成Jar的方式如下:

我已经通过单击“+”符号添加了资源文件夹。但是,当我调用生成的Jar文件时,它仍然报错FileNotFoundException。

有什么建议吗?

new File代表一个文件。例如,一个文件。 jar 文件中的条目不是文件。

您的代码无法满足您的要求。

文件是错误的抽象。您需要 InputStream 或 URL,它们都可以表示文件、网络流、即时生成的内容,以及 jar 文件中的条目。

public void readFile(String fileName) {
  try (var in = ThisClass.class.getResourceAsStream(fileName)) {
    Scanner scanner = new Scanner(in, StandardCharsets.UTF_8);
    // proceed here.
  } catch (IOException e) {
    throw new RuntimeException("Uncaught", e);
  }
}

该片段中发生了一些事情:

  • 使用 ThisClass.class,而不是 getClass()。当您子类化时,getClass 路由中断。您可能不会在这里这样做,但您以后可能会这样做;最好编写在尽可能短的情况下始终有效的代码。
  • 这是一个资源,您必须关闭它。因此,此代码使用 try-with-resources。
  • 我们得到一个 InputStream(getResourceAsStream returns 一个输入流),这是可以表示 jar 中的条目的正确抽象级别(对比 File 它只能'不要那样做)。
  • 我们告诉扫描器字符集编码是什么。否则你会得到平台默认值,这是错误和令人讨厌的:在你自己的计算机上它总是可以工作,然后你 运行 它在另一个系统上并且它失败了。始终,始终在字节转换为字符(反之亦然)时指定字符集编码。
  • e.printStackTrace() 是邪恶的。永远不要以这种方式处理异常。如果您不知道(这在这里很公平;如果这会抛出 IOEx,显然有严重错误,最好让您的应用程序尽可能详细地崩溃)——以上是正确的处理方法它。