Java读取资源.wav时出现异常

3

我觉得我的代码没问题,我的.jar文件里也包含了.wav文件。但是当我尝试使用getResourceAsStream加载它时,出现了错误。

我的错误如下:

java.io.IOException: mark/reset not supported
    at java.util.zip.InflaterInputStream.reset(Unknown Source)
    at java.io.FilterInputStream.reset(Unknown Source)
    at com.sun.media.sound.SoftMidiAudioFileReader.getAudioInputStream(Unkno
wn Source)
    at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
    at operation.MainWindowOperations.prepareAudio(MainWindowOperations.java
:92)
    at operation.MainWindowOperations.<init>(MainWindowOperations.java:81)
    at graphics.LaunchGraphics.<init>(LaunchGraphics.java:25)
    at run.RunApp.main(RunApp.java:14)

这是我的代码:
private void prepareAudio() {
    try {

        InputStream is = this.getClass().getClassLoader().getResourceAsStream("beep.wav");
        inputStream = AudioSystem.getAudioInputStream(is);
        clip = AudioSystem.getClip();
        clip.open(inputStream);

    } catch (Exception ex) {
        ex.printStackTrace();

    }

}

有人可以帮我吗?非常感谢!


1
你可以在这个帖子中找到你的答案。 - user973999
@EricR。+1 这个帖子包含了两个我不知道的潜在快捷方式。 - Andrew Thompson
它对我不起作用,它给了我另一个错误... 流已关闭.. - TiagoM
使用这个解决方案,我得到了这个结果,但是我不明白为什么。我的代码在这里: http://pastebin.com/8wamm4E1提前感谢大家 ;) - TiagoM
一道有趣的问题,我从中学到了一些关于流的知识。 :) - Andrew Thompson
2个回答

6

Java Sound需要对某些操作使用可重定位(支持标记/重置)的输入流。如果您遇到此问题,则是因为该流不可重定位。

解决此问题的一种方法是将原始流的byte[]放入支持标记/重置的ByteArrayInputStream中。


连接到Eric R.的问题的第二个答案也是一种可能性,看起来更简单。要尝试它,请更改..

InputStream is = this.getClass().getClassLoader().getResourceAsStream("beep.wav");
inputStream = AudioSystem.getAudioInputStream(is);

致:

URL url = this.getClass().getClassLoader().getResource("beep.wav");
inputStream = AudioSystem.getAudioInputStream(url);

真的吗?Java 在处理声音方面似乎很糟糕 :s 我需要使用一个字节数组?然后循环整个数组并播放每个字节?:s 提前致谢。 - TiagoM
不需要循环整个数组,只需将ByteArrayInputStream传递给AudioSystem.getAudioInputStream(..),其余代码可以按原样工作。 - Andrew Thompson
@Andrew - 包含“URL”答案的+1。这个问题似乎会多次出现。ByteArrayInputStream的答案是一个巧妙的解决方法,但事实证明当所有人都可以通过通过URL加载来避免从音频文件创建InputStream时,它是过度的。 - Phil Freihofner
我尝试实现你告诉我的第二个选项,但是在URL上出现了错误,因为我将beep.wav放在了项目根目录下,我将其更改为包文件夹,在那里我有我的类加载资源。现在它可以正常工作了。非常感谢你的第二个选项!它非常好用!非常感谢你,伙计! - TiagoM
很高兴你解决了它。我不像处理getResource()返回的URL那样经常处理getResourceAsStream()返回的流。原因之一是我喜欢将URL记录在日志中以进行健全性检查。记录输入流提供的信息较少有用。;) - Andrew Thompson
显示剩余2条评论

2

在JavaRanch上,Tim Moores的帮助下,我得到了答案。尽管Andrew在他的回答的第二部分提到了这个正确的答案,但我认为最清晰的方法就是在这里发布它。(第一部分也可以,但是有些过度设计。)

Url url = this.getClass().getResource("beep.wav");           
inputStream = AudioSystem.getAudioInputStream(url);

http://www.coderanch.com/t/558274/Applets/java/mark-reset-not-supported-getResourceAsStream

Tim写道:我对这个问题或者applet中的音频没有具体的了解,但是我不惊讶mark/reset不能与通过ClassLoader机制获取的资源一起使用。(实际上,我有点惊讶它能工作,至少有些时候 :-)

假设音频文件通过HTTP是公开可访问的,请尝试使用AudioSystem.getAudioInputStream(URL)而不是您现在使用的InputStream版本。查看javax.sound.sampled.spi.AudioFileReader javadocs(这是底层正在使用的类),只有InputStream变量谈论到mark/reset问题,而不是URL版本。

这也出现在这里:https://forums.oracle.com/forums/thread.jspa?threadID=2289395&tstart=0,答案在底部,其中包括一个Oracle Bug参考号#7095006,这是一个有趣的阅读,因为它解释了为什么代码(如最初尝试的op)曾经可以工作,但现在不再工作。


谢谢Andrew!我记得你也是给我第一个+10分的人。新年快乐! - Phil Freihofner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接