2012-04-02 67 views
3

它可以与传递给AudioSystem#getAudioFileFormatFile对象一起使用,但为什么它会在下面的对象InputStream失败?任何建议?无法将InputStream对象传递给Java Sound API

import java.io.*; 
import javax.sound.sampled.*; 

public class Test { 

    public static void main(String[] args) throws Exception { 

     AudioSystem.getAudioFileFormat(new File(
       "myaudio.wav")); 
     AudioSystem.getAudioFileFormat(new FileInputStream(
       "myaudio.wav")); 

    } 
} 

输出:

Exception in thread "main" java.io.IOException: mark/reset not supported 
    at java.io.InputStream.reset(InputStream.java:330) 
    at com.sun.media.sound.WaveFileReader.getAudioFileFormat(WaveFileReader.java:88) 
    at javax.sound.sampled.AudioSystem.getAudioFileFormat(AudioSystem.java:985) 
    at Test.main(Test.java:10) 

@EDIT

@René Jeschke@Phil Freihofner@Andrew Thompson,无论mark/reset被要求作为强制性protocal的Java Sound API与之交互的答案IO stream,恕我直言,的类型流而不是raw一个应该是特别是定义为要传递的参数的签名。这样做会比任意接受IO stream,然后使用IOException作为不利指标而缩小到更理想的结果。

回答

4

FileInputStream不支持标记/重置(对于随机访问),将其包装到BufferedInputStream以获得标记/重置支持。

编辑:这是为什么? getAudioFileFormat迭代当前注册的每个音频文件读取器。每个阅读器试图通过读取一些特定的字节来识别文件格式。因此,每个读者必须对其流进行更改(以允许其他读者在需要时重新读取所有数据)。

当您提供File时,这不是问题,因为每个阅读器只是打开一个新的流,但是当您传递一个流时,每个阅读器都必须标记当前流的位置,读取它并将流重置为其开始状态完成时。

这就是为什么你需要BufferedInputStream,因为它增加了一个内存缓冲区来支持标记/重置。

Edit2:因为问题是'为什么它会因FileInputStream失败?'我没有提出任何解决方法或替代方案,但试图解释为什么在使用FileInputStream时失败。还有一些情况下,您不能使用URL或类似的东西(例如考虑包含音频文件的二进制包文件)。

+0

这个问题已经出现了多次,并且可能会继续这样做。解释并不糟糕,但我很痛苦,因为使用BufferedInputStream的提议“解决方案”会增加不必要的工作,因为可以通过URL加载并完全避免标记/重置问题。 – 2012-04-03 22:12:32

+0

当我研究这个问题,并对问题有了更好的理解时,我意识到这个答案中提供的信息是相当不错的,而且我非常关键地给它一个-1。我很乐意给它一个+1来抵消我的第一反应,但是我不能这样做,除非你的答案被编辑。非常抱歉! (如果您在编辑时收到通知,我不确定是否会收到通知,但如果您在此处留下备注,我会收到通知,并且会返回来纠正我的错误。) – 2012-04-04 00:56:06

+0

我在回答中添加了一个小脚注。没关系,@PhilFreihofner ;-) – Neet 2012-04-04 10:05:08

1

这适用于我(与其他Wavs)。

AudioSystem.getAudioFileFormat(new File(
      "myaudio.wav").toURI().toURL()); 

JavaSound info. page上的代码也使用URL。

如果你有什么东西既不是FileURL,这个问题可以通过缓冲其固定,由勒内Jeschke提到的,或者我一般只读取所有byte[]并建立ByteArrayInputStream。那定位(支持标记/重置)。

1

AudioSystem.getAudioFileFormat()方法调用包javax.sound.sampled.spi中的抽象类“AudioFileReader”。

AudioFileFormat getAudioFileFormat(InputStream stream) throws UnsupportedAudioFileException, IOException;说可能要求标记/复位的方法代码中的注释:形式public abstract AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException; public abstract AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException;

* Obtains the audio file format of the input stream provided. The stream must 
* point to valid audio file data. In general, audio file readers may 
* need to read some data from the stream before determining whether they 
* support it. These parsers must 
* be able to mark the stream, read enough data to determine whether they 
* support the stream, and, if not, reset the stream's read pointer to its original 
* position. If the input stream does not support this, this method may fail 
* with an <code>IOException</code>. 

相反,不作此要求。对解析器的支持只会以InputStream作为参数。

AudioSystem.getAudioInputStream()同样针对各种重载进行了注释。

当在使用音频文件的环境中出现标记/重置错误时,首先尝试的解决方案是通过URL加载文件,从而避免标记/重置要求(如Andrew Thompson所述)。如果这不起作用,当然可以使用BufferedInputStream,但它不应该用于有效的音频文件。

该问题在Oracle Bug数据库中也记录为错误#7095006。