Failed to pass InputStream object to Java Sound API
It works with the object File
passed in AudioSystem#getAudioFileFormat
, but why doesn't it work with the object InputStream
below? Any suggestion?
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"));
}
}
Output:
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
According to the answers @René Jeschke
, @Phil Freihofner
and @Andrew Thompson
where mark/reset
it is required as a mandatory protocol to Java Sound API
interact with IO stream
, IMHO, the type of buffered
stream raw
should instead be specifically , which is defined as the signature of the passed parameter. This will narrow down to a more desirable outcome than arbitrarily accept IO stream
and then resort to IOException
as an unfavorable indicator.
source to share
FileInputStream
doesn't support mark / reset (for random access), wrap it in BufferedInputStream
to get mark / reset support.
Edit: Why is this the case? getAudioFileFormat
iterates through each registered audio file. Each reader tries to identify the file format by reading some specific bytes. Therefore, each reader should undo their changes in the stream (so that other readers can re-read all the data, if necessary).
When you supply File
this is not a problem, because each reader just opens a new stream, but when you submit a stream, each reader has to mark the current position of the stream, do their readings, and reset the stream before it starts when it's finished.
That's why you need it BufferedInputStream
, because it adds an in-memory buffer to support the / reset label.
Edit2: Because the question is, "Why doesn't this work with FileInputStream?" I haven't offered any workarounds or replacements, but tried to explain why it fails if you are using FileInputStream
. There are also cases where you cannot use a URL or the like (consider, for example, a binary package file containing audio files).
source to share
This works for me (with other Wavs).
AudioSystem.getAudioFileFormat(new File(
"myaudio.wav").toURI().toURL());
Code in JavaSound info. the page also uses the url.
If you have something that is not File
or the URL
problem can be fixed by buffering it as mentioned by Rene Yeschke, or I generally just read everything byte[]
and installed it ByteArrayInputStream
. This positioned (supports mark / reset).
source to share
The AudioSystem.getAudioFileFormat () methods call the abstract class "AudioFileReader" in the javax.sound.sampled.spi package.
The comments in the code of the method AudioFileFormat getAudioFileFormat(InputStream stream) throws UnsupportedAudioFileException, IOException;
say that a / reset may be required:
* 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 read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an <code>IOException</code>.
On the contrary, form public abstract AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException;
and public abstract AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException;
DO NOT make this requirement. Support for parsers only with InputStream as a parameter.
AudioSystem.getAudioInputStream () are similarly commented out for various overloads.
When the / reset tag error occurs in the context of working with audio files, the solution for the first try is to download the file from its url and thus avoid the / reset tag requirement (as mentioned by Andrew Thompson). If that doesn't work, of course use a BufferedInputStream, but it shouldn't come to this for valid audio files.
The issue is also documented in the Oracle Bug database as bug # 7095006.
source to share