【问题标题】:intelliJ IDEA add resources to JARIntelliJ IDEA 向 JAR 添加资源
【发布时间】:2018-11-18 09:37:50
【问题描述】:

我有一个使用资源(.wav .png- 文件)的应用程序。 我想在构建项目时将这些资源包含在我的 .jar 中。

从 IDE 运行应用程序效果很好。

here 所述,我在src-folder 的同一级别创建了resources-folder

我的项目结构:

ProjectName --        
              |
              out
              |
              resources --
              |           |
              |           sounds
              |           |
              |           images
              src --
                    |
                    ...

here 所述,我已将文件夹resources 标记为Resources root

here 所述,我在Project structure 中创建了自己的工件。 这就是他们的样子:

一段代码,例如与音频文件一起使用:

new Media(new File("resources/sounds/login_sound.wav").toURI().toString());

当我尝试通过终端运行 jar 时,我收到以下错误:

Caused by: MediaException: MEDIA_UNAVAILABLE : /home/moritz/IdeaProjects/TheFloorIsLavaGUI/out/artifacts/TheFloorIsLavaGUI_jar/resources/sounds/login_sound.wav (File or directory not found)

完整的堆栈跟踪:

    moritz@Momix:~/IdeaProjects/TheFloorIsLavaGUI/out/artifacts/TheFloorIsLavaGUI_jar$ java -jar TheFloorIsLavaGUI.jar 
Gtk-Message: 12:33:12.649: Failed to load module "canberra-gtk-module"
Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:748)
Caused by: MediaException: MEDIA_UNAVAILABLE : /home/moritz/IdeaProjects/TheFloorIsLavaGUI/out/artifacts/TheFloorIsLavaGUI_jar/resources/sounds/login_sound.wav (Datei oder Verzeichnis nicht gefunden)
    at javafx.scene.media.Media.<init>(Media.java:407)
    at managers.SoundManager.playSong(SoundManager.java:71)
    at main.TheFloorIsLavaGUI.start(TheFloorIsLavaGUI.java:39)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$48(GtkApplication.java:139)
    ... 1 more
Exception running application main.TheFloorIsLavaGUI

有什么建议吗? 谢谢

【问题讨论】:

    标签: intellij-idea jar artifacts


    【解决方案1】:

    TL;DR:

    从类路径而不是从文件系统加载文件:

    new Media(
      Test.class.getResource(
        "resources/sounds/login_sound.wav"
       ).toURI().toString())`
    

    解释:这里发生了几件事:

    • 您正在尝试从路径/your/home/.../project/out/artifacts/.../resources/... 加载文件。通过将 resources 标记为资源文件夹,您可以告诉 IntelliJ 将所有文件放在类路径的根目录中,如屏幕截图所示。

    • 它不会将该文件放入文件系统中,而是将其包含在 jar 中

    • 从 IDE 运行时,new File("resources/sounds/login_sound.wav").toURI() 的计算结果为 /home/moritz/IdeaProjects/TheFloorIsLavaGUI/resources/sounds/login_sound.wav,这是您项目中文件的位置。从 jar 运行时,它会计算输出文件夹中的路径 /home/moritz/IdeaProjects/TheFloorIsLavaGUI/out/artifacts/TheFloorIsLavaGUI_jar/resources/sounds/login_sound.wav,这不是构建放置它的位置。

    现在,处理这个问题的正确方法是不从文件系统而是从类路径加载资源。尝试从 IDE 和 jar 中运行以下命令以查看差异

    System.out.println(new File("foo.wav").toURI().toString());
    System.out.println( Test.class.getResource("foo.wav").toURI().toString());
    
    // From IDE
    file:/Users/.../untitled/foo.wav
    file:/ Users/.../untitled/out/production/untitled/foo.wav
    
    // From Jar
    file:/Users/.../untitled/out/artifacts/foo.wav
    jar:file: /Users/.../untitled/out/artifacts/untitled_jar/untitled.jar!/foo.wav
    

    请注意,Media 接受 jar URI:https://docs.oracle.com/javafx/2/api/javafx/scene/media/Media.html#Media%28java.lang.String%29

    所以你需要做的其实很简单。 将加载 wav 从 new Media(new File("resources/sounds/login_sound.wav").toURI().toString()); 更改为 new Media(Test.class.getResource("resources/sounds/login_sound.wav").toURI().toString())

    除此之外:您可能希望研究 gradle 或 maven 等构建工具,而不是从 IDE 构建。

    【讨论】:

      猜你喜欢
      • 2011-08-27
      • 2012-08-03
      • 1970-01-01
      • 1970-01-01
      • 2015-10-31
      • 1970-01-01
      • 1970-01-01
      • 2016-08-27
      • 2013-05-14
      相关资源
      最近更新 更多