Mp3(ID3v2)格式文件解析


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文件格式解析请参考下面文章:
点击打开链接


  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值