简体   繁体   English

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

[英]Trouble with .wav playing in jar file created from Intellij IDEA

Apologies if this has been asked before, but I was unable to find an answer that worked for us.如果之前有人问过这个问题,我深表歉意,但我找不到适合我们的答案。 I am also a beginner so please bear with me.我也是初学者,所以请多多包涵。

Essentially, after jarring our code the audio stopped working.本质上,在我们的代码震动之后,音频停止工作。

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

I have tried using getResourceAsStream and getResource as apparently files don't work properly when jarred but it still does not work even in Intellij.我已经尝试使用 getResourceAsStream 和 getResource,因为显然文件在受到干扰时无法正常工作,但即使在 Intellij 中它仍然无法正常工作。

My code is located in the src folder and the music location is being passed to the code like so:我的代码位于 src 文件夹中,音乐位置被传递给代码,如下所示:

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

Images are working properly in the jar file.图像在 jar 文件中正常工作。

Edit: it appear that the jar file is unable to take the audio files, which are within another folder that is otherwise being accessed, because the file size of the jar does not change after the deletion of the.wav files.编辑:似乎 jar 文件无法获取音频文件,这些文件位于另一个正在访问的文件夹中,因为 jar 的文件大小在删除 .wav 文件后没有改变。

Edit 2:编辑 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;
    }
}

This is the coe we are attempting to use.这是我们正在尝试使用的 coe。 The musicLocation String is passed in the format of: /folder/file.wav After manually putting the.wav files into the jar through winrar, it still is unable to load the music in the jar file.传递的musicLocation String格式为: /folder/file.wav通过winrar手动将.wav文件放入jar后,仍然无法加载jar文件中的音乐。

Edit 3:Attempting to use URL Class, receiving NullPointerException编辑 3:尝试使用 URL Class,收到 NullPointerException

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

When passed into the AudioInputStream as a file with the "src" before the location name, it does not pass a null.当作为位置名称前带有“src”的文件传递到 AudioInputStream 时,它不会传递 null。

Edit 4: Attempting to use URL Class with the file inside of folder in Music class package编辑 4:尝试将 URL Class 与音乐文件夹中的文件一起使用 class package

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

With the audio folder above being inside the classes (containing all the.java files) package, this returns a NullPointerException.上面的音频文件夹位于类中(包含所有 .java 文件)package,这将返回 NullPointerException。 After adding a "Classes/" to the front, hovering over the string in my IDE allows me to "see" that the file is correctly being sourced if you will but it still returns a NullPointerException to the.wav file.在前面添加“Classes/”后,将鼠标悬停在我的 IDE 中的字符串上可以让我“看到”如果您愿意,该文件的来源是正确的,但它仍然会向 .wav 文件返回 NullPointerException。

Edit 5: Receiving this error after implementing Phil's code编辑 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

Edit 6: Displaying class that resulted in error above编辑 6:显示导致上述错误的 class

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);
    }
}

Edit 7: Phils identical set of code worked upon moving project to Eclipse. I'm still unsure of why it didn't work in Intellij but my problem was solved n.netheless.编辑 7:Phils 相同的代码集在将项目移动到 Eclipse 时起作用。我仍然不确定为什么它在 Intellij 中不起作用,但我的问题已经解决了。 Thanks to everyone who offered their help!感谢所有提供帮助的人!

The java.io.File object is not a good choice for addressing files that are packed in jars. I don't know the correct technical way to explain this, but in simple language, it can only address files that are in file folders. java.io.File object不是寻址 jars 中打包的文件的好选择。我不知道解释这个的正确技术方法,但简单来说,它只能寻址文件夹中的文件。 It has no ability to "see" within jar files.它无法“查看”jar 个文件。

For this reason, it's more usual to access the file by getting its URL using the Class.getResource method.因此,更常见的做法是使用Class.getResource方法获取其URL来访问该文件。 A URL can identify a file that has been compressed and is located within a jar. URL可以标识已压缩的文件,位于 jar 中。

It is also possible to address and load a sound file in a jar using the .getResourceAsStream method.也可以使用 .getResourceAsStream 方法在.getResourceAsStream中寻址和加载声音文件。 This method returns an InputStream , not a URL .此方法返回一个InputStream ,而不是一个URL But this is a dicier option.但这是一个更冒险的选择。 If you look at the API for the overloaded AudioSystem.getAudioInputStream , and compare the versions, you'll see that if the argument is an InputStream , the file will be subjected to tests to determine if "mark" and "reset" are supported.如果查看重载的AudioSystem.getAudioInputStream的 API 并比较版本,您会发现如果参数是InputStream ,文件将接受测试以确定是否支持“标记”和“重置”。 A sizable number of audio files fail these tests.大量音频文件未通过这些测试。 For this reason, it's safer to use the method with a URL argument.因此,使用带有URL参数的方法会更安全。

Problems can also arise in how the file name is provide in the getResource method, but usually if the name String works in the DAW it will also work in a jar (assuming you are obtaining a URL and not a File).getResource方法中如何提供文件名也会出现问题,但通常如果名称 String 在 DAW 中有效,它也将在 jar 中有效(假设您获得的是 URL 而不是文件)。 The specifics about "relative" and "root" addressing aren't the easiest to explain.关于“相对”和“根”寻址的细节并不是最容易解释的。 But we can go there if needed.但如果需要,我们可以拨打 go。

EDIT: Code example for troubleshooting.编辑:用于故障排除的代码示例。

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);
    }    
}

The code assumes the following file folder structure:该代码采用以下文件夹结构:

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

Note that the file name is case sensitive.请注意,文件名区分大小写。 A null value for the URL indicates that the file is not at the expected location. URL 的 null 值表示文件不在预期位置。 First get this working in your IDE, and maybe prefer either your console or File Explorer to verify the file structure and file location.首先在您的 IDE 中运行它,并且可能更喜欢您的控制台或文件资源管理器来验证文件结构和文件位置。

If you try running the above and have problems, the exact code as entered and stack trace would be helpful.如果您尝试运行上面的代码并遇到问题,输入的确切代码和堆栈跟踪将很有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM