【发布时间】:2015-12-26 19:18:52
【问题描述】:
我正在尝试用 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 一个无符号字符(八位字节)值。
Z 一个以 null 结尾的 (ASCIZ) 字符串,将填充为 null。
我的程序的输出:
标题内容
标签:ID3
版本:3
版本:0
标志:0
尺寸:699
输出错误!
框架内容
编号:TPE1
尺寸:167772160
标志:
Perl 的正确输出!
框架内容
编号:TPE1
尺寸:10
标志:0
【问题讨论】:
-
我无法回答您的问题。你说“它给了我大约 140000 字节”,然后你说你看到了
size: 1677772160。这是一个错误还是我误解了你? -
这是我的错误,现在应该更正了。正确的输出是 10,错误的输出是 167772160。对于 1400000 的混淆,您可以忘记,我很抱歉。