在从 Intellij IDEA 创建的 jar 文件中播放 .wav 时出现问题

Posted

技术标签:

【中文标题】在从 Intellij IDEA 创建的 jar 文件中播放 .wav 时出现问题【英文标题】:Trouble with .wav playing in jar file created from Intellij IDEA 【发布时间】:2020-12-07 00:14:26 【问题描述】:

抱歉,如果以前有人问过这个问题,但我无法找到适合我们的答案。我也是初学者,请多多包涵。

基本上,在破坏我们的代码后,音频停止工作。

clip = Audiosystem.getClip();
             File file = new File(musicLocation);
             clip.open(AudioSystem.getAudioInputStream(file.getAbsoluteFile()));
             clip.start();

我尝试过使用 getResourceAsStream 和 getResource,因为显然文件在 jarred 时无法正常工作,但即使在 Intellij 中它仍然无法正常工作。

我的代码位于 src 文件夹中,音乐位置被传递给代码,如下所示:

filepath = "src/Images/music/click.wav"; 
musicObject.playMusic(filepath);

图像在 jar 文件中正常工作。

编辑:jar 文件似乎无法获取音频文件,这些文件位于另一个正在访问的文件夹中,因为 jar 的文件大小在删除 .wav 文件后没有改变。

编辑 2:

public class Music 
    Clip loop;
    void loopMusic(String musicLocation) 
        try 
            loop = AudioSystem.getClip();
            InputStream is = getClass().getResourceAsStream(musicLocation);
            AudioInputStream audioS = AudioSystem.getAudioInputStream(is);
            loop = AudioSystem.getClip();
            loop.open(audioS);
            loop.start();
            loop.loop(Clip.LOOP_CONTINUOUSLY);
         catch (Exception e) 
            System.out.println(e);
        
    
    void stopLoop()
        if (loop != null) 
            loop.stop();
            loop.close();
        
        loop=null;
    

这是我们尝试使用的 coe。 musicLocation 字符串以以下格式传递:/folder/file.wav 通过winrar手动将.wav文件放入jar后,仍然无法加载jar文件中的音乐。

编辑 3:尝试使用 URL 类,收到 NullPointerException

URL musicLocation = this.getClass().getResource("/Images/music/battle.wav");
AudioInputStream inputStream = AudioSystem.getAudioInputStream(musicLocation);

当作为位置名称前带有“src”的文件传递到 AudioInputStream 时,它不会传递空值。

编辑 4:尝试将 URL 类与 Music 类包中文件夹内的文件一起使用

URL musicLocation = this.getClass().getResource("audio/battle.wav");
AudioInputStream inputStream = AudioSystem.getAudioInputStream(musicLocation);

由于上面的音频文件夹位于类(包含所有 .java 文件)包中,这将返回 NullPointerException。在前面添加“Classes/”后,将鼠标悬停在我的 IDE 中的字符串上可以让我“看到”该文件是否被正确获取,但它仍会向 .wav 文件返回 NullPointerException。

编辑 5: 执行 Phil 的代码后收到此错误

Exception in thread "main" java.lang.ExceptionInInitializerError
    at Classes.Frame.<init>(Frame.java:15)
    at Classes.GraphicsRunner.main(GraphicsRunner.java:15)
Caused by: java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:222)
    at java.desktop/javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1032)
    at Classes.Music.<init>(Music.java:16)
    at Classes.Panel.<clinit>(Panel.java:24)
    ... 2 more

编辑 6:显示导致上述错误的类

package Classes;

import javax.sound.sampled.*;
import javax.swing.*;
import java.io.*;
import java.net.URL;

public class Music 
    Clip clip;

    // Constructor, create looping audio resource, hold in memory.
    public Music() 
        URL url = this.getClass().getResource("audio/battle.wav");
        AudioInputStream ais;
        try 
            ais = AudioSystem.getAudioInputStream(url);
            //line 16 above 
            DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
            clip = (Clip) AudioSystem.getLine(info);
            clip.open(ais);
         catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) 
            e.printStackTrace();
        
    

    public void play() 
        clip.setFramePosition(0);
        clip.loop(Clip.LOOP_CONTINUOUSLY);
    

编辑 7:Phils 使用相同的代码集将项目移至 Eclipse。我仍然不确定为什么它在 Intellij 中不起作用,但我的问题仍然解决了。感谢所有提供帮助的人!

【问题讨论】:

这能回答你的问题吗? Get audio to play in JAR File 也适合:Music not playing in .JAR-file 在实现getResourceAsStream 和getAudioInputStream 后,就像下面说的,它仍然不起作用。 【参考方案1】:

java.io.File 对象不是用于寻址打包在 jar 中的文件的好选择。我不知道解释这一点的正确技术方法,但用简单的语言,它只能处理文件夹中的文件。它无法在 jar 文件中“看到”。

因此,更常见的是通过使用Class.getResource 方法获取其URL 来访问该文件。 URL 可以识别已压缩并位于 jar 中的文件。

还可以使用.getResourceAsStream 方法在 jar 中寻址和加载声音文件。此方法返回InputStream,而不是URL。但这是一个更冒险的选择。如果您查看重载的AudioSystem.getAudioInputStream 的 API,并比较版本,您会看到如果参数是 InputStream,文件将接受测试以确定“mark”和“reset”是否为支持的。相当数量的音频文件未通过这些测试。因此,使用带有URL 参数的方法会更安全。

getResource 方法中如何提供文件名也可能会出现问题,但通常如果名称 String 在 DAW 中有效,它也可以在 jar 中有效(假设您获取的是 URL 而不是文件) .关于“相对”和“根”寻址的细节并不是最容易解释的。但如果需要,我们可以去那里。

编辑:用于故障排除的代码示例。

public class Music 
    Clip clip;

    // Constructor, create looping audio resource, hold in memory.
    public Music() 
        URL url = this.getClass().getResource("audio/battle.wav");
        AudioInputStream ais;
        try 
            ais = AudioSystem.getAudioInputStream(url);
            DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
            clip = (Clip) AudioSystem.getLine(info);
            clip.open(ais);
         catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) 
            e.printStackTrace();
        
    

    public void play() 
        clip.setFramePosition(0);
        clip.loop(Clip.LOOP_CONTINUOUSLY);
        

代码假定以下文件夹结构:

/src/.../folderwithMusic/Music
/src/.../folderwithMusic/audio/battle.wav

请注意,文件名区分大小写。 URL 的空值表示文件不在预期的位置。首先让它在你的 IDE 中运行,可能更喜欢你的控制台或文件资源管理器来验证文件结构和文件位置。

如果您尝试运行上述程序并遇到问题,输入的确切代码和堆栈跟踪会有所帮助。

【讨论】:

@Tom,在问题的 cmets 中,链接了该问题的先前迭代,其中包括建议使用 URL 而不是 File 作为 AudioSystem.getAudioInputStream 中的参数。我已将此作为更明确的答案,因为在这些问题中可能很容易忽略此解决方案,因为这些帖子中提供了许多建议。 感谢您的回复。您是否知道为什么使用 WinRar 打开时 .wav 文件没有出现在 jar 文件中的问题?另外,我尝试使用 URL 类,并使用上面的代码进行了编辑 这一行让我很困惑:“通过 winrar 手动将 .wav 文件放入 jar 之后”。我不清楚你到底在做什么!您愿意尝试以下方法吗? (它可能不是首选的项目结构,但它有助于排除故障。)在“this”所在的文件夹(编辑 3)中,创建一个名为“audio”的子文件夹。将音频文件(“battle.wav”)放在该文件夹中,然后再压缩项目,确保刷新项目。使用 Edit 3,基于 URL 的代码,使用字符串“audio/battle.wav”调用此文件。这应该在 IDE 和 jarring 之后都有效。 接收到空指针异常,尽管文件被正确获取。已用我尝试过的内容进行了编辑 在上面编辑了结果。您对文件夹结构的假设是我构建路径的方式。

以上是关于在从 Intellij IDEA 创建的 jar 文件中播放 .wav 时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

使用具有 mysql 数据库的 IntelliJ IDEA 创建 Jar 文件

使用IntelliJ IDEA创建第一个Mawen项目

IntelliJ Idea - 如何在从数据库表生成域对象时指定选项

如何在 IntelliJ IDEA 中创建 .jar 文件或导出 JAR(如 Eclipse Java 存档导出)? [复制]

在 IntelliJ IDEA 中创建 Java Gradle 项目并构建 .jar 文件 - 如何?

Intellij IDEA在maven项目中添加外部Jar包运行