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

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在我的消息对话框中。

我该如何解决这个问题?

AudioSystem.getAudioInputStream(InputStream)的文档说:

这个方法的实现可能需要多个parsing器来检查stream,以确定它们是否支持它。 这些parsing器必须能够标记stream,读取足够的数据以确定它们是否支持stream,如果不支持,则将stream的读取指针重置为原始位置。 如果inputstream不支持这些操作,则此方法可能会因IOException而失败。

因此,您提供给此方法的stream必须支持可选的标记/重置function。 用BufferedInputStream装饰你的资源stream。

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

经过一段时间的讨论,并多次引用这个页面,我偶然发现了这个帮助我解决问题的方法。 我最初能够加载一个WAV文件,但随后只能播放一次,因为它不能倒回由于“标记/重置不支持”的错误。 这是疯了。

链接的代码从文件中读取一个AudioInputStream,然后将AudioInputStream放入一个BufferedInputStream中,然后将放回到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更好地处理标记/重置。 希望这可以帮助那里的人。

刚刚从其他人引用这个问题的同样的问题。

Oracle Bug数据库,#7095006

使用下面的代码来避免InputStream步骤。 这是导致错误的InputStream。

 URL url = AudioMixer.class.getResource(fileName); AudioInputStream ais = AudioSystem.getAudioInputStream(url); 

瞧 – 没有InputStream

在getAudioInputStream()期间标记/重置exception

问题是你input的stream必须支持方法标记和重置。 至less如果标记被支持,你可以使用: AudioInputStream#markSupported进行testing。

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