最近使用java来获取音乐的基本信息,从网上找了一些支持包,可能是比较老的原因,mp3包读取总是失败,所幸http://www.javazoom.net/mp3spi/mp3spi.html 提供的包中是有源码的,我所遇到的问题是通过输入流来获取音频时长总是获取不到。跟踪代码MpegAudioFileReader 的getAudioFileFormat(InputStream inputStream, long mediaLength) 方法,发现
if (mLength != AudioSystem.NOT_SPECIFIED)
{
nTotalMS = Math.round(m_header.total_ms(tmpLength));
aff_properties.put("duration", new Long((long) nTotalMS * 1000L));
}
duration (时长)的获取首先判断mLength是否赋值,而这个mLength的值来自mediaLength
int mLength = (int) mediaLength;
mediaLength 即文件的长度,因我之前调用的AudioSytem获取reader再调getAudioFileFormat(InputStream inputStream),而这个过程最后调用的是MpegAudioFileReader父类TAudioFileReader的getAudioFileFormat(InputStream inputStream),这个方法
long lFileLengthInBytes = AudioSystem.NOT_SPECIFIED;
if (!inputStream.markSupported()) {
inputStream = new BufferedInputStream(inputStream, getMarkLimit());
}
inputStream.mark(getMarkLimit());
AudioFileFormat audioFileFormat = null;
try
{
audioFileFormat = getAudioFileFormat(inputStream, lFileLengthInBytes);
}
调用子类MpegAudioFileReader getAudioFileFormat时确实没有指定文件长度,于是我将调用修改一下,直接来调MpegAudioFileReader,但是还是报错,根据错误原因找到代码
if ((size == mediaLength) && (mediaLength != AudioSystem.NOT_SPECIFIED))
{
// FileInputStream fis = (FileInputStream) inputStream;
byte[] id3v1 = new byte[128];
// long bytesSkipped = fis.skip(inputStream.available() - id3v1.length);
// int read = fis.read(id3v1, 0, id3v1.length);
if ((id3v1[0] == 'T') && (id3v1[1] == 'A') && (id3v1[2] == 'G'))
{
parseID3v1Frames(id3v1, aff_properties);
}
}
如果指定长度会走到FileInputStream fis = (FileInputStream) inputStream; 但是我传的输入流不一定是FileInputStream,这句话自然会抛出异常,幸好fis其实什么也没干,于是注释掉,代码运行OK!