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