【问题标题】:sound not playing in jar声音没有在罐子里播放
【发布时间】:2011-02-07 16:46:20
【问题描述】:

我已将所有类文件和资源打包为一个 jar,但在执行时声音文件不会播放。我的包结构是:

+project
|_classes
|_ _*.class
|_resources
|_ _ *.jpg,*.wav

代码:

AudioInputStream inputStream = AudioSystem.getAudioInputStream(kidsClassRoom.class.getResourceAsStream("../resources/"+file));

执行此行时获得null!!

【问题讨论】:

    标签: java jar javasound


    【解决方案1】:

    已经提出的理论的替代理论。通常成功的 getResource() 调用依赖于调用来定位它们的类加载器实例。出于这个原因,我建议使用用户定义对象的实例,从中调用 getResource()。例如

    // Sanity check
    System.out.println("The value of 'file' is: " + file);
    // Presuming kidsClassRoom1 is an instance of kidsClassRoom
    AudioInputStream inputStream = AudioSystem.
        getAudioInputStream(
            kidsClassRoom1.
                getClass().
                getResourceAsStream("/resources/"+file));
    

    您可能还注意到,sn-p 为资源使用前缀“/”。与其他人所说的相反,我相信这意味着资源路径的“从根”,在运行时类路径上的任何 Jar 中找到它。留下“/”或“../”将使类加载器在发生这种情况的类的子路径中搜索资源。

    当然 - 确保 Wav 最终出现在 Jar 中!将 .jar 复制/重命名为 .zip 并双击它是在 Windows 上检查存档内容的“快速而肮脏”的方式。

    【讨论】:

    • 你能解释一下为什么 kidsClassRoom1.getClass() 比 kidsClassRoom.class 更好吗?
    • 我不确定。有不同的类加载器。用于从 J2SE 加载内容的引导类加载器不会发现应用程序运行时类路径上的类或资源。查找应用程序的最佳类加载器。 resources 是一个上下文类加载器。使用 className.class 可能会产生上下文类加载器,也可能不会。 OTOH 使用自定义类的实际对象实例保证使用上下文类加载器。但最重要的是——这个建议对你有用吗?是否“找到”了 wav 文件?
    • kidsClassRoom.class 方式对我有用。问题是我输入了错误的文件名!!
    【解决方案2】:

    创建一个名为resources的包如下图

    然后

     AudioSystem.getAudioInputStream(kidsClassRoom.class.getResourceAsStream("resources/"+file));
    

    【讨论】:

    • 没有任何文件夹Foo 会做,但是kidsClassRoom.class.getResourceAsStream("Foo/"+file)
    • 只需在任何存档工具中打开 jar 文件并将快照放在这里,我想检查结构
    • 我在询问 jar 的快照,当它在某个归档器中打开以检查已打包的 dir 结构时
    • jar 中没有资源目录。 :) 你是怎么打包的?
    • 内部类目录:jar -cmvf0 manif.txt kidsClassRoom.jar *.class ../resources/*.*
    【解决方案3】:

    这是我在 jar 中播放循环声音文件的功能,它对我来说很好。

    getResourceAsStream() 似乎不适用于罐子。但是,getResource() 可以。

    public synchronized void alarm() {
        try {
            crit = AudioSystem.getClip();
            AudioInputStream inputStream1 = AudioSystem.getAudioInputStream(this.getClass().getResource("critical.wav"));
            crit.open(inputStream1);
            crit.loop(Clip.LOOP_CONTINUOUSLY);
    
        } catch (Exception e) {
            System.err.println(e.getMessage());
            }
    }
    

    【讨论】:

      【解决方案4】:

      当你做getResourceAsStream 时,它不是相对于当前类,而是相对于档案的根。即先尝试删除../

      【讨论】:

      • 尝试右键单击资源文件夹并选择“构建路径 -> 用作源文件夹”。 (这只是为了确保从 Eclipse 启动时类加载器可以访问这些文件。)
      • 我现在没有使用任何 IDE :)
      • 啊哈,我明白了,然后确保该文件夹是类路径的一部分(如果您的类位于 bin 中,请使用 -cp resources:bin。(如果您使用 ; 而不是 : '在窗户上。)
      • 当你做 getResourceAsStream 时,它与当前类无关,but the root of the archive。也就是说,首先尝试删除 ../.哪个是根文件夹?
      • 啊,好问题。我相信它会按照它们在-cp-argument 中出现的顺序搜索类路径的每个文件夹。
      【解决方案5】:

      需要注意的重要一点是,在导出的 jar 中,资源不存储为文件(请在某处阅读此内容,请了解更多知识的人输入)。因此最好先将资源作为 URL 对象获取,然后将其传递给 AudioInputStream 对象。

      URL url = YourClass.class.getResource(filename);
      AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
      

      如果资源位于子文件夹中,请记住将其添加到您的文件名路径中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-29
        • 1970-01-01
        相关资源
        最近更新 更多