如何构建包含外部文件的 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,显然有严重错误,最好让您的应用程序尽可能详细地崩溃)——以上是正确的处理方法它。
我想将资源文件夹中的文本文件包含到 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,显然有严重错误,最好让您的应用程序尽可能详细地崩溃)——以上是正确的处理方法它。