提问人:Kayla Clayton 提问时间:7/18/2023 更新时间:8/13/2023 访问量:43
尝试使用 clip 在 java 8 中播放声音会抛出 java.lang.NullPointerException
Trying to play a sound in java 8 using clip is throwing java.lang.NullPointerException
问:
我目前正在编写一个小游戏,并尝试实现背景音乐。我对 Java 中的视觉/音频很陌生,在网上做了一些研究后,我发现 Clip 将是一个与我制作图形的方式兼容的选项。因此,我遵循了有关如何设置/使用它的教程,从而产生了这个“声音”类:
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.*;
public class Sound implements LineListener {
boolean isPlaybackCompleted;
int playMode;
public Sound(int mode) {
playMode = mode; // 0 = background music
}
@Override
public void update(LineEvent event) {
if (LineEvent.Type.START == event.getType()) {
isPlaybackCompleted = false;
System.out.println("Playback started.");
} else if (LineEvent.Type.STOP == event.getType()) {
isPlaybackCompleted = true;
System.out.println("Playback completed.");
}
}
public void playSound(String soundName) throws LineUnavailableException, IOException, UnsupportedAudioFileException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("./Sounds/facilityIndoors.wav");
AudioInputStream audioStream = AudioSystem.getAudioInputStream(inputStream);
AudioFormat audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.addLineListener(this);
audioClip.open(audioStream);
audioClip.start();
switch(playMode){
case 0:
if(isPlaybackCompleted == true) {
}
}
audioClip.close();
audioStream.close();
}
}
(请注意,playSound 的“soundName”参数是我希望稍后实现的,这样我就可以根据与当前地图名称共享的变量在轨道之间切换,并且当前未使用,我刚刚将路径硬编码为现在已经存在的文件以供测试)
我在我的主
Sound music = new Sound(0);
music.playSound(map.currentMap);
但是,当我尝试调用playSound函数时,此错误会抛出:
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:209)
at java.desktop/javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1006)
at Sound.playSound(Sound.java:37)
at Program.main(Program.java:22)
起初我以为我拼错了文件路径,但仔细检查后我的拼写似乎是正确的,如下所示: 文件路径和文件名的图像 “Global Research FacilityJava8”是我的项目文件夹,我的图像引用似乎是从该级别开始的,所以也许 Clip 不是从项目文件夹开始的,这可能是问题所在, 但如果是,我不知道如何解决。
我尝试检查文件路径中的拼写错误,并尝试从一开始就省略一些符号(例如,只是“Sounds/facilityIndoors.wav”或“/Sounds/facilityIndoors.wav”),但错误仍然存在。在发布此内容之前检查可能的重复列表时,我还发现了一篇帖子,讨论将我所有的资源文件夹放入一个“资源”文件夹中并将其添加到构建路径中,我现在已经尝试过,但无济于事,仍然抛出相同的错误。(文件路径现在为“resources/Sounds/facilityIndoors.wav”)
答:
我遇到了同样的问题,但我没有找到解决它的方法,而是决定通过将音频文件复制到我 PC 上的某个位置来解决它。
尝试以下代码来复制文件
File audio = new File("C://somewhere//audio.wav").mkdir();
Files.copy(getClass().getResourceAsStream("resources/Sounds/facilityIndoors.wav"), Paths.get("C://somewhere//audio.wav"), StandardCopyOption.REPLACE_EXISTING);
现在只需像这样使用该文件audio
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audio));
Clip audioClip = AudioSystem.getClip();
audioClip.open(audioStream);
评论
Exception in thread "main" java.lang.ClassCastException: class com.sun.media.sound.DirectAudioDevice$DirectSDL cannot be cast to class javax.sound.sampled.Clip (com.sun.media.sound.DirectAudioDevice$DirectSDL and javax.sound.sampled.Clip are in module java.desktop of loader 'bootstrap') at Sound.playSound(Sound.java:35) at Program.main(Program.java:21)
Sound.java:32
获得正确的声音文件的地址通常很棘手。如果未在地址中指定起始“/”,则搜索是相对于 .setResource 或 .getResourceAsStream 方法引用的类进行的。在您发布的内容中,您在保存该类的文件夹中是否有子文件夹 /Sounds?否则,将收到 null 错误。Sound
“/”作为地址的前缀应该从项目文件夹开始搜索,但我承认我对它到底是如何工作的有些模糊。(我通常即时生成声音而不是参考资源,所以我不经常使用它)。我认为,例如,基于 Maven 的项目使用 /src/main/resources 文件夹,而其他 Java 项目使用 /src。但我必须对此进行测试才能确认。
它可能不再有任何区别,但作为旁注,我认为最好使用返回 的 .getResource() 而不是返回 .后者更挑剔,例如,如果底层文件不支持标记或重置操作,AudioSystem.getAudioInputStream() 将拒绝。如果向 .getAudioInputStream() 提供 ,则不需要支持标记和重置。如果比较重载,可以在 AudioSystem.getAudioStream() 的 API 中了解此内容。用作参数(第三个重载)通常不是一个好的选择,因为 Java 无法在 Jar 中找到文件。URL
InputStream
InputStream
URL
File
评论