除非我提取文件,为什么我的Jar不会运行?

时间:2014-09-26 09:33:43

标签: java image swing jar export

每次我运行导出的.jar文件时,其中包含JFrame图片作为图标,文件无法运行,除非我提取文件。在编译器中它正在运行。我不想制作一个将资源包和jar文件保存在目录中的启动程序。

1 个答案:

答案 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应该是相对于调用它的类或类加载器。以下是几种不同的方式:

  1. 如图所示

    URL url = getClass().getResource("/resources/image.png");
    

    注意/。这将把我们带到类路径的根,resources目录将在那里。 URL可以传递给许多构造函数,例如ImageIcon(URL)或`ImageI.read(URL)

  2. 您可以使用:

    InputStream is = getClass().getResourceAsStream("/resources/image.png");
    

    将使用引擎盖下的URL。您也可以将InputStream与许多构造函数一起使用。

  3. 还有使用类加载器的方法,它将从根开始,因此您不需要/

    URL url = getClass().getClassLoader().getResource("resources/image.png");
    
  4. 所以有几种方法可以解决它。但一般来说,使用嵌入式资源时,使用硬编码字符串路径读取File绝不是一个好主意。可以动态获取路径,因此您可以使用File,但您仍然需要使用上述技术之一,除非您确实需要File,否则将毫无意义您可以使用InputStreamURL

    执行所需操作

    长话短说

    这样可行

    ProjectRoot
           src\resources\image.png
    
    URL url = getClass().getResource("/resources/image.png");
    Image image = ImageIO.read(url);