它适用于传递给File
对象的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"));
}
}
输出:
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/reset
作为Java Sound API
与IO stream
、IMHO交互的强制协议,buffered
流的类型(而不是raw
流)应该是(特别是E 216
)定义为要传递的参数的签名。这样做将缩小到比任意接受IO stream
,然后求助于IOException
作为不利指标更理想的结果。
发布于 2012-04-02 08:53:53
FileInputStream
不支持标记/重置(用于随机访问),将其包装到BufferedInputStream
中以获得标记/重置支持。
编辑:为什么会这样?getAudioFileFormat
遍历当前注册的每个音频文件阅读器。每个阅读器都试图通过读取一些特定的字节来标识文件格式。因此,每个读取器都必须撤销对流的更改(如果需要,允许其他读取器重新读取所有数据)。
当您提供一个File
时,这不是一个问题,因为每个读取器只是打开一个新的流,但是当您传递一个流时,每个阅读器必须标记当前流的位置,做它的读取,并在它完成时将流重置到它的起始状态。
这就是为什么您需要BufferedInputStream
,因为它添加了一个内存中的缓冲区来支持标记/重置。
Edit2:因为问题是“为什么FileInputStream失败了?”我没有提出任何解决办法,也没有提出替代方案,但我试图解释为什么在使用FileInputStream
时它会失败。在有些情况下,您不能使用URL等(例如,包含音频文件的二进制包文件)。
发布于 2012-04-02 09:04:02
这适用于我(与其他Wavs)。
AudioSystem.getAudioFileFormat(new File(
"myaudio.wav").toURI().toURL());
JavaSound info. page上的代码也使用一个URL。
如果你所拥有的不是File
或URL
,问题可以通过缓冲来解决,就像勒内·耶施克提到的那样,或者我通常只是阅读所有的byte[]
并建立一个ByteArrayInputStream
。是可定位的(支持标记/重置)。
发布于 2012-04-03 22:30:32
AudioSystem.getAudioFileFormat()方法调用包javax.sound.sampled.spi中的抽象类"AudioFileReader“。
方法AudioFileFormat getAudioFileFormat(InputStream stream) throws UnsupportedAudioFileException, IOException;
的代码中的注释指出,可能需要标记/重置:
*获取所提供的输入流的音频文件格式。流必须*指向有效的音频文件数据。通常,音频文件读取器可能需要从流中读取一些数据,然后才能确定它们是否支持它。这些解析器必须*能够标记流,读取足够的数据以确定它们是否支持流,如果不支持,则将流的读取指针重置为原始的*位置。如果输入流不支持这一点,这个方法可能会失败*与一个IOException。
相反,表单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。
https://stackoverflow.com/questions/9973369
复制相似问题