我正在尝试读取c ++中的mp3文件并显示该文件包含的id3信息。我遇到的问题是,当我读取帧头时,它所容纳的内容大小错误。而不是给我10字节的整数,而是给我167772160字节。http://id3.org/id3v2.3.0#ID3v2_frame_overview
struct Header {
char tag[3];
char ver;
char rev;
char flags;
uint8_t hSize[4];
};
struct ContentFrame
{
char id[4];
uint32_t contentSize;
char flags[2];
};
int ID3_sync_safe_to_int(uint8_t* sync_safe)
{
uint32_t byte0 = sync_safe[0];
uint32_t byte1 = sync_safe[1];
uint32_t byte2 = sync_safe[2];
uint32_t byte3 = sync_safe[3];
return byte0 << 21 | byte1 << 14 | byte2 << 7 | byte3;
}
const int FRAMESIZE = 10;
上面的代码用于将二进制数据转换为ASCCI数据。主要内部
Header header;
ContentFrame contentFrame;
ifstream file(argv[1], fstream::binary);
//Read header
file.read((char*)&header, FRAMESIZE);
//This will print out 699 which is the correct filesize
cout << "Size: " << ID3_sync_safe_to_int(header.hSize) << endl << endl;
//Read frame header
file.read((char*)&contentFrame, FRAMESIZE);
//This should print out the frame size.
cout << "Frame size: " << int(contentFrame.contentSize) << endl;
我已经在Perl中为此任务编写了一个程序,并且运行良好,其中使用了unpack,例如:
my($tag, $ver, $rev, $flags, $size) = unpack("Z3 C C C N"), "header");
my($frameID, $FrameContentSize, $frameFlags) = unpack("Z4 N C2", "content");
也可以使用sync_safe_to_int来正确设置标头的大小,但是对于竞争大小,它仅用于打印任何转换 N以“网络”(大端)顺序的无符号长(32位)。
C一个无符号的char(八位位组)值。
ZA以null终止的(ASCIZ)字符串,将以null填充。
我程序的输出:
标头内容
标签:ID3
版本:3版本
:0
标志:0
大小:699
错误输出!框架内容
ID:TPE1
大小:167772160
标志:
从Perl正确输出!帧内容
ID:TPE1
大小:10
标志:0
contentFrame.contentSize
定义为uint32_t
,但打印为(signed)int
。
另外,如文档所述,多字节数字为Big Endian:
ID3v2中的位顺序是最高有效位在先(MSB)。多字节数字中的字节顺序是最高有效字节在先(例如$ 12345678将被编码为$ 12 34 56 78)。
contentFrame.contentSize
但是,不进行任何转换。这些字节也应该反转,如中所述ID3_sync_safe_to_int()
,但是这次以8的倍数而不是7的倍数移位(或使用ntohl()
-网络到主机顺序)。
您说得到的是1677772160而不是18,但是即使对上面的位/字节进行了操作,它们似乎也没有意义。您确定这些数字正确吗?在您的帖子之上,您还有其他价值:
与其给我不足100个字节的完整记录,不如给我大约140000个字节。
调用后,您是否查看了内存中的字节file.read((char*)&contentFrame, FRAMESIZE);
?但是,如果您的身份证显示TPE1
位置应该可以。我只是想知道您提供的数字是否正确,因为它们没有意义。
更新nthol()
转换:
//Read frame header
file.read((char*)&contentFrame, FRAMESIZE);
uint32_t frame_size = ntohl(contentFrame);
cout << "Frame size: " << frame_size << endl;
ntohl()
将在LE系统和BE系统上运行(在BE系统上,它不会运行)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句