无法将InputStream对象传递给Java Sound API

时间:2012-04-02 08:50:27

标签: java javasound

它适用于传递给File的{​​{1}}个对象,但为什么它会因下面的AudioSystem#getAudioFileFormat对象而失败?有什么建议吗?

InputStream

输出:

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

    }
}

@EDIT

根据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) @René Jeschke@Phil Freihofner的答案,只要@Andrew Thompson作为mark/resetJava Sound API互动的强制性协议, 1}},恕我直言,IO stream流而不是buffered流的类型应该特别定义为要传递的参数的签名。这样做会缩小到比任意接受raw然后诉诸IO stream作为不利指标更令人满意的结果。

3 个答案:

答案 0 :(得分:5)

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

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

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

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

Edit2:因为问题是'为什么它会因FileInputStream而失败?'我没有建议任何变通方法或替换,但试图解释为什么当使用FileInputStream时失败。在某些情况下,您无法使用URL等(例如,考虑包含音频文件的二进制包文件)。

答案 1 :(得分:1)

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

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

JavaSound info. page上的代码也使用了网址。

如果你所拥有的东西既不是File也不是URL,那么问题就可以通过缓存来修复,如RenéJeschke所说,或者我通常只是阅读所有{{1}并建立一个byte[] 可定位(支持标记/重置)。

答案 2 :(得分:1)

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

方法AudioFileFormat getAudioFileFormat(InputStream stream) 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>.

相比之下,表单public abstract AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException; public abstract AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException; 不要提出这个要求。对解析器的支持仅提供InputStream作为参数。

AudioSystem.getAudioInputStream()也针对各种重载进行了类似的评论。

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

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