在日常的工作中,我们经常需要进行一些二进制文件或协议的读写操作,用C#解析二进制文件常常是一件比较麻烦且容易出错的工作,本文介绍了一种在C#中实现快速读写二进制文件通用的方法。
以一个解析Mp3 ID3V1标签头为例,ID3V1标签保存在MP3文件尾的最后128个字节用来存放ID3信息,其格式具体如下表:
字节 |
长度 (字节) |
说明 |
1-3 |
3 |
存放"TAG"字符,表示ID3 V1.0标准。 |
4-33 |
30 |
歌名 |
34-63 |
30 |
作者 |
64-93 |
30 |
专辑名 |
94-97 |
4 |
年份 |
98-127 |
30 |
附注 |
128 |
1 |
MP3音乐类别,共147种。 |
如果要用C/C++语言来解析这个标签头,一般需要经过如下两个步骤:
首先定义标签头数据结构,
typedefstructtagID3V1
{
char Header[3]; /*标签头必须是"TAG"否则认为没有标签*/
char Title[30]; /*标题*/
char Artist[30]; /*作者*/
char Album[30]; /*专集*/
char Year[4]; /*出品年代*/
char Comment[28]; /*备注*/
char reserve; /*保留*/
char track; /*音轨*/
char Genre; /*类型*/
}ID3V1;
C/C++语言定义的数据结构非常清晰的指明了各字段所占用的内存和偏移位置,由于C语言定义的数据结构是和内存中的偏移位置直接对应上的,因此,定义后数据结构后,从文件中获取数据到数据结构是非常简单的事情。PS:这是个c++的版本,由于只是个示例代码,去掉了异常处理相关流程,C语言版本类似,这里就不举例了。
void main()
{
ifstream file("r:\\te2st.mp3");
ID3V1 id3v1 = {0}; //存放读取的mp3 ID3V1信息
file.seekg((int)(-1*sizeof(id3v1)), ios::end);
file.read((char*)(&id3v1), sizeof(id3v1));
}
从这段代码中可以看到,只需要通过内存拷贝函数就可以将数据从数据一口气复制到数据结构中来,无需手动一个个成员赋值,非常简洁。
现在我们再来看看