每次我运行导出的.jar
文件时,其中包含JFrame
图片作为图标,文件无法运行,除非我提取文件。在编译器中它正在运行。我不想制作一个将资源包和jar文件保存在目录中的启动程序。
答案 0 :(得分:5)
"除非我提取文件,为什么我的Jar不会运行?"
这似乎是将File
用于资源的行为。举个例子
File file = new File("resources/image.png");
Image image = ImagIO.read(file);
你的项目结构(请注意resources
实际上应该在src
中,以便它自动构建到jar中 - 除非你以不同的方式配置它。但是为了这个论点,让& #39; s说你做在jar中构建resources
的地方进行配置)
C:\
Project
resources\image.png
一些检查:
从IDE运行 - 工作!为什么?使用File
查找文件系统上的文件。使用相对路径,搜索将从"工作目录"开始,在IDE的情况下通常是项目根目录。因此"resources/image.png"
是相对于ProjectRoot
构建jar,说它最终在项目的dist
目录中。这就是它的样子
ProjectRoot
dist
ProjectRoot.jar
现在为了这个论点(并且实际上是正确的方法),让我们尝试在out程序中打印资源的URL,这样当你运行jar时,它会打印出来的URL。文件
URL url = Test.class.getResource("/resources/image.png");
System.out.println(url.toString());
当我们运行jar C:\ProjectRoot\dist> java -jar ProjectRoot.jar
时,我们会看到打印出C:\ProjectRoot\dist\ProjectRoot.jar!\resources\image.png
。显然,即使当前工作目录是jar的位置,路径不再匹配,添加的jar ProjectRoot.jar!
位置也可以看到。
那么为什么我们提取它时它会起作用。那么当你提取它时,路径是正确的
C:\ProjectRoot
dist
resources/image.png // from extracted jar
ProjectRoot.jar
从C:\ProjectRoot\dist >
开始运行时,resource
目录应该在哪里。
关于解释已经足够了。
出于这个原因,当你想要阅读嵌入式资源时,应该像Andrew Thompson所提到的那样从URL中读取它们。这个url应该是相对于调用它的类或类加载器。以下是几种不同的方式:
如图所示
URL url = getClass().getResource("/resources/image.png");
注意/
。这将把我们带到类路径的根,resources
目录将在那里。 URL
可以传递给许多构造函数,例如ImageIcon(URL)
或`ImageI.read(URL)
您可以使用:
InputStream is = getClass().getResourceAsStream("/resources/image.png");
将使用引擎盖下的URL。您也可以将InputStream
与许多构造函数一起使用。
还有使用类加载器的方法,它将从根开始,因此您不需要/
URL url = getClass().getClassLoader().getResource("resources/image.png");
所以有几种方法可以解决它。但一般来说,使用嵌入式资源时,使用硬编码字符串路径读取File
绝不是一个好主意。可以动态获取路径,因此您可以使用File
,但您仍然需要使用上述技术之一,除非您确实需要File
,否则将毫无意义您可以使用InputStream
或URL
这样可行
ProjectRoot
src\resources\image.png
URL url = getClass().getResource("/resources/image.png");
Image image = ImageIO.read(url);