Java 无法读取MP3帧头字节?

Java 无法读取MP3帧头字节?,java,mp3,wave,Java,Mp3,Wave,我正在用java开发一个音频项目,该项目要求我根据音频文件的数据(而不是文件扩展名)来确定音频文件的类型,我已经用MP3遇到了麻烦。据我所知,MP3文件分为多个帧,每个帧都有一个4字节的头文件,其中包含11个用于帧同步的头文件和一系列其他数据。现在我的代码可以准确地识别WAVE文件,但是当我开始读取测试MP3文件的字节时,我在任何地方都找不到11111111字节(11帧同步位中的前8个) try { FileInputStream fis = new FileInputStrea

我正在用java开发一个音频项目,该项目要求我根据音频文件的数据(而不是文件扩展名)来确定音频文件的类型,我已经用MP3遇到了麻烦。据我所知,MP3文件分为多个帧,每个帧都有一个4字节的头文件,其中包含11个用于帧同步的头文件和一系列其他数据。现在我的代码可以准确地识别WAVE文件,但是当我开始读取测试MP3文件的字节时,我在任何地方都找不到11111111字节(11帧同步位中的前8个)

try {
        FileInputStream fis = new FileInputStream(f);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buff = new byte[11];
        byte[] byteData;
        int bytes = 0;

        while ((bytes = fis.read(buff)) != -1) {
            baos.write(buff, 0, buff.length);
        }

        byteData = baos.toByteArray();

        fis.close();
        baos.close();

        if ((int)byteData[0] == 255) {
            type = "MP3";
        } else if (("" + (char)byteData[8] + (char)byteData[9] + 
                (char)byteData[10] + (char)byteData[11]) == "WAVE") {
            type = "WAVE";
        }

    }

您可能会发现MP3文件的前三个字节是:

49 44 33
这是带有ID3v2标签的MP3的“神奇数字”

编辑

好的,我看了一下我的系统,我的MP3包含了一个神奇的数字:

73 68 51
在ascii中是“ID3”

请注意,您的字节操作有一些问题。。。。当您根据int值测试字节值时,您需要确保正确地进行转换。。。。测试:

byte x = ....;
if (x == 255) {...}
对于“x”的任何值都不会为真,因为
(byte)x
的范围为-128到+127

要使此测试正常工作,您需要执行以下操作:

if ((x & 0xff) == 255) { .... }
我已经修改了你的方法,在我的系统上进行了测试,并尝试了一个WAV文件和一些MP3。这是我的代码:

public static final String getValid(File f) throws IOException {
    FileInputStream fis = new FileInputStream(f);
    byte[] buff = new byte[12];
    int bytes = 0, pos = 0;

    while (pos < buff.length && (bytes = fis.read(buff, pos, buff.length - pos)) > 0) {
        pos += bytes;
    }

    fis.close();

   // this is your test.... which should bitmask the value too:
    if ((buff[0] & 0x000000ff) == 255) {
        return "MP3 " + f;
    }
    // My testing indicates this is the MP3 magic number
    if (   'I' == (char)buff[0]
        && 'D' == (char)buff[1]
        && '3' == (char)buff[2]) {
        return "MP3 ID3 Magic" + f;
    }
    // This is the magic number from wikipedia (spells '1,!')
    if (49 == buff[0] && 44 == buff[1] && 33 == buff[2]) {
        return "MP3 ID3v2" + f;
    }
    if (   'W' == (char)buff[8]
        && 'A' == (char)buff[9]
        && 'V' == (char)buff[10]
        && 'E' == (char)buff[11]) {
        return "WAVE " + f;
    }

    return "unknown " + f;

}
public静态最终字符串getValid(文件f)引发IOException{
FileInputStream fis=新的FileInputStream(f);
字节[]buff=新字节[12];
int字节=0,pos=0;
而(pos0){
pos+=字节;
}
fis.close();
//这是您的测试…它也应该位掩码值:
if((buff[0]&0x000000ff)==255){
返回“MP3”+f;
}
//我的测试表明这是MP3的神奇数字
如果('I'==(字符)buff[0]
&&'D'==(字符)buff[1]
&&'3'==(字符)buff[2]){
返回“MP3 ID3魔术”+f;
}
//这是维基百科上的神奇数字(拼写为“1,!”)
如果(49==buff[0]&&44==buff[1]&&33==buff[2]){
返回“MP3 ID3v2”+f;
}
如果('W'==(char)buff[8]
&&'A'==(字符)buff[9]
&&“V'==(字符)buff[10]
&&“E”==(字符)buff[11]){
返回“波”+f;
}
返回“未知”+f;
}

现在我读取的第一个字节是
-1-5-78
,它不知何故没有终止while循环。我存储信息的方式可能有错误吗?是的,你做错了,我要编辑我的答案。。。。但首先,您是否打算只读取前11个字节?是的,文件的完整内容在别处读取。我意识到当前返回的字节是正确的,因为
-1-5
包含我要查找的初始11位。不过,我仍然不能完全确定这是否是进行MP3验证的最佳方法。编辑了我的答案。注意两件事-不需要ByteArrayOutputStream和字节操作。
49 44 33
来自的“十六进制签名”列(相当于十进制
73 68 51
和US-ASCII
ID3
)。