2011-04-03 53 views
52
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 supportedjava.io.IOException:不支持標記/重置

我該如何解決這個問題?

回答

113

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); 
+3

泰,這個工作。我修改了這樣的代碼: 'BufferedInputStream myStream = new BufferedInputStream(getClass()。getResourceAsStream(「mySound.au」)); AudioInputStream audio2 = AudioSystem.getAudioInputStream(myStream);' 現在它工作=) P.S.如果有人可以格式化這個評論,它會很棒=/ – Crais 2011-04-03 15:05:17

+0

這是什麼標記/重置意味着什麼?可以查找的流? @McDowell,你可以在你的答案中顯示裝飾的代碼嗎? – 2011-08-02 20:08:52

+0

@Shurane - 標記/重置允許在調用重置時(通常通過從標記被調用時緩衝RAM中的數據)將「未讀」數據流回到標記點。 – McDowell 2011-08-03 07:31:40

0

的問題是,你輸入流必須支持的方法標記和復位。至少如果支持標記,您可以使用:AudioInputStream#markSupported進行測試。

所以你應該使用不同的InputStream。

5

約掙扎了一會兒,引用此頁面多次後,我碰到this這讓我與我的問題絆倒了。我最初能夠加載一個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處理mark/reset比audioInputStream更好。希望這可以幫助那裏的人。

+0

這裏的其他解決方案不適用於我的問題,但這是一個!謝謝! – 2014-03-29 00:38:12

4

過這個問題,剛剛從別人誰與它引用了同樣的問題。

Oracle錯誤數據庫,#7095006

使用下面的代碼,以避免InputStream的一步。這是導致錯誤的InputStream。

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

瞧 - 沒有的InputStream

mark/reset exception during getAudioInputStream()

+1

我可以在哪裏獲得AudioMixer?我嘗試了一個類似帖子中的鏈接,但它指向其他地方。 – 2012-08-02 13:49:22

+2

@Potney對不起。 AudioMixer確實看起來可能是核心Java類的名稱,但它只是我寫的一個類。我在代碼源中使用它的目錄位置作爲查找「文件名」的起點。 http://docs.oracle.com/javase/tutorial/uiswing/components/icon.html如果您還不熟悉這一點,請參閱上述教程中的「使用getResource加載圖像」一節。 – 2012-08-02 17:18:35