Mp3(ID3v2)格式文件解析

来源:互联网 发布:vep视觉训练软件 编辑:程序博客网 时间:2024/05/23 23:20


ID3v2版本的标签分析:

1、标签头
在文件的首部顺序记录 10 个字节的 ID3V2.3 的头部。数据结构如下:
 char Header[3];     /*必须为"ID3"否则认为标签不存在*/
 char Ver;     /*版本号 ID3V2.3 就记录 3*/
 char Revision;     /*副版本号此版本记录为 0*/
 char Flag;     /*存放标志的字节,这个版本只定义了三位,稍后详细解说*/
 char Size[4];     /*标签大小,包括标签头的 10 个字节和所有的标签帧的大小*/

1).标志字节
 标志字节一般为 0,定义如下:
 abc00000
 a -- 表示是否使用 Unsynchronisation(这个单词不知道是什么意思,字典里也没有找到,一般不设置)
 b -- 表示是否有扩展头部,一般没有(至少 Winamp 没有记录),所以一般也不设置
 c -- 表示是否为测试标签(99.99%的标签都不是测试用的啦,所以一般也不设置)
 2).标签大小
 一共四个字节,但每个字节只用 7 位,最高位不使用恒为 0。所以格式如下
 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx

计算要求要把每个字节的最高位0位丢弃,所以我们可以通过左移二进制位数和位运算来实现这个问题,示例代码如下:

 public static int toSize(byte[] bytes){        int result = bytes[0] << 21                | bytes[1] << 14                | bytes[2] << 7                | bytes[3];        return result;    }

2、标签帧
每个标签帧都有一个 10 个字节的帧头和至少一个字节的不固定长度的内容组成。                    它们也是顺序存放在文件
中,和标签头和其他的标签帧也没有特殊的字符分隔。得到一个完整的帧的内容只有从帧头中的到内容大
小后才能读出,读取时要注意大小,不要将其他帧的内容或帧头读入。
帧头的定义如下:
 char FrameID[4];   /*用四个字符标识一个帧,说明其内容,稍后有常用的标识对照表*/
 char Size[4];    /*帧内容的大小,不包括帧头,不得小于 1*/
 char Flags[2];    /*存放标志,只定义了 6 位,稍后详细解说*/
 1).帧标识
 用四个字符标识一个帧,说明一个帧的内容含义,常用的对照如下:
 TIT2=标题 表示内容为这首歌的标题,下同
 TPE1=作者
 TALB=专集
 TRCK=音轨 格式:N/M        其中 N 为专集中的第 N 首,M 为专集中共 M 首,N 和 M 为 ASCII 码表示的数字
 TYER=年代 是用 ASCII 码表示的数字
 TCON=类型 直接用字符串表示
 COMM=备注 格式:"eng/0 备注内容",其中 eng 表示备注所使用的自然语言
 2).大小
 这个可没有标签头的算法那么麻烦,每个字节的 8 位全用,格式如下
 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
示例代码如下:

public static int toSize2(byte[] data) {        int result = data[0] << 24                | data[1] << 16                | data[2] << 8                | data[3];        return result;    }
练习代码:Tes01.java

public class Test01 {    public static void main(String[] args) {        try {            //FileInputStream需要一个文件地址            FileInputStream fis = new FileInputStream("ss.mp3");//            System.out.println(fis.available());//            System.out.println((char) fis.read());//            System.out.println(fis.available());            byte[] bytes = new byte[3];            int length = fis.read(bytes);            System.out.println(length);            String s = new String(bytes, 0, length);            System.out.println(s);            System.out.println(fis.read());            System.out.println(fis.read());            System.out.println(fis.read());            System.out.println("===========");            byte[] size = new byte[4];            fis.read(size);            int l = toSize(size);            System.out.println(l);            byte[] data = new byte[l-10];            fis.read(data);            int index = 0;            while (index < data.length){                System.out.println(new String(data, index, 4));                index+=4;                int nameSize = toSize2(data, index);                index+=4;                index+=2;                System.out.println(nameSize);                System.out.println(new String(data, index, nameSize));                index+=nameSize;            }//            fis.skip(fis.available() - 128);//            byte[] bytes = new byte[128];//            fis.read(bytes);//            System.out.println(new String(bytes, 0, 3));        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }    }    public static int toSize(byte[] bytes){        int result = bytes[0] << 21                | bytes[1] << 14                | bytes[2] << 7                | bytes[3];        return result;    }    public static int toSize2(byte[] data, int offset) {        int result = data[offset] << 24                | data[offset + 1] << 16                | data[offset + 2] << 8                | data[offset + 3];        return result;    }}
map3文件格式解析请参考下面文章:
点击打开链接


0 1
原创粉丝点击