java.io.IOException:不支持标记/重置

问题描述 投票:0回答:5
try {
    //String location = dir1.getCanonicalPath()+"\\app_yamb_test1\\mySound.au";
    //displayMessage(location);
    AudioInputStream audio2 = AudioSystem.getAudioInputStream(getClass().getResourceAsStream("mySound.au"));
    Clip clip2 = AudioSystem.getClip();
    clip2.open(audio2);
    clip2.start();
} catch (UnsupportedAudioFileException uae) {
    System.out.println(uae);
    JOptionPane.showMessageDialog(null, uae.toString());
} catch (IOException ioe) {
    System.out.println("Couldn't find it");
    JOptionPane.showMessageDialog(null, ioe.toString());
} catch (LineUnavailableException lua) {
    System.out.println(lua);
    JOptionPane.showMessageDialog(null, lua.toString());
}

当我从 netbeans 运行应用程序时,此代码工作正常。声音响起,没有任何异常。但是,当我从 dist 文件夹运行它时,声音不会播放,并且我在消息对话框中看到

java.io.IOException: mark/reset not supported

我该如何解决这个问题?

java audio ioexception
5个回答
171
投票

AudioSystem.getAudioInputStream(InputStream)
的文档说:

该方法的实现可能 需要多个解析器来检查 流来确定它们是否 支持它。这些解析器必须能够 标记流,读取足够的数据 以确定他们是否支持 流,如果没有,则重置 流的读指针指向其原始流 位置。如果输入流没有 支持这些操作,这个方法 可能会因 IOException 失败。

因此,您提供给此方法的流必须支持可选的 mark/reset 功能。用

BufferedInputStream
.

装饰您的资源流
//read audio data from whatever source (file/classloader/etc.)
InputStream audioSrc = getClass().getResourceAsStream("mySound.au");
//add buffer for mark/reset support
InputStream bufferedIn = new BufferedInputStream(audioSrc);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(bufferedIn);

6
投票

在挣扎了一段时间并多次引用此页面后,我偶然发现了this,它帮助我解决了我的问题。我最初能够加载 wav 文件,但随后只能播放一次,因为由于“不支持标记/重置”错误而无法倒带。真让人抓狂。

链接的代码从文件中读取 AudioInputStream,然后将 AudioInputStream 放入 BufferedInputStream,然后将 that 放回 AudioInputStream,如下所示:

audioInputStream = AudioSystem.getAudioInputStream(new File(filename));
BufferedInputStream bufferedInputStream = new BufferedInputStream(audioInputStream);
audioInputStream = new AudioInputStream(bufferedInputStream, audioInputStream.getFormat(), audioInputStream.getFrameLength());

最后将读取的数据转换为 PCM 编码:

audioInputStream = convertToPCM(audioInputStream);

convertToPCM 定义为:

private static AudioInputStream convertToPCM(AudioInputStream audioInputStream)
    {
        AudioFormat m_format = audioInputStream.getFormat();

        if ((m_format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) &&
            (m_format.getEncoding() != AudioFormat.Encoding.PCM_UNSIGNED))
        {
            AudioFormat targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                m_format.getSampleRate(), 16,
                m_format.getChannels(), m_format.getChannels() * 2,
                m_format.getSampleRate(), m_format.isBigEndian());
            audioInputStream = AudioSystem.getAudioInputStream(targetFormat, audioInputStream);
    }

    return audioInputStream;
}

我相信他们这样做是因为 BufferedInputStream 比 audioInputStream 更好地处理标记/重置。希望这对那里的人有帮助。


5
投票

刚刚从其他有同样问题的人那里看到这个问题并引用了它。看起来这个问题是在 Java 7 中出现的。

Oracle Bug 数据库,#7095006

InputStream
getAudioInputStream()
方法的参数时执行的测试会触发错误。音频资源文件中是否存在标记/重置功能与
Clip
是否加载和播放无关。鉴于此,当
InputStream
URL
就足够时,没有理由更喜欢使用
File
作为参数。

如果我们替换

URL
作为参数,则不会执行这个不必要的测试。修改OP代码:

AudioInputStream ais = AudioSystem.getAudioInputStream(getClass().getResource(fileName));

详细信息可以在 API 中看到,在两种形式的描述文本中。 AudioSystem.getAudioInputStream(InputStream)

AudioSystem.getAudioInputStream(URL)


1
投票

问题是你的输入流必须支持标记和重置方法。至少如果支持标记,您可以使用以下命令进行测试:AudioInputStream#markSupported

所以你也许应该使用不同的InputStream。


0
投票

我解决了类似的问题,你的代码看起来像这样,由你来尝试。

try {
InputStream is = getClass().getResourceAsStream("mySound.au");
BufferedInputStream bis = new BufferedInputStream(is);
Clip clip2 = AudioSystem.getClip();
clip2.open(bis);
clip2.start();
} catch (UnsupportedAudioFileException uae) {
System.out.println(uae);
JOptionPane.showMessageDialog(null, uae.toString());
} catch (IOException ioe) {
System.out.println("Couldn't find it");
JOptionPane.showMessageDialog(null, ioe.toString());
} catch (LineUnavailableException lua) {
System.out.println(lua);
JOptionPane.showMessageDialog(null, lua.toString());
}
© www.soinside.com 2019 - 2024. All rights reserved.