我在C中制作一个id3标签编辑器。我无法弄清楚如何从二进制文件末尾拉出最后128个字节,以便操作/打印出id3标签所在的区域。下面是一些代码:
struct Tag{
char tagMark[3];
char trackName[30];
char artistName[30];
char albumName[30];
char year[4];
char comment[30];
char genre;
};
int main(int argc, char *argv[]){
struct Tag fileTag;
FILE *fp;
fp=fopen(argv[0], "r+b");
if(!fp){
printf("ERROR: File does not exist.");
}
int bufLength=129;
fseek(fp, 0, SEEK_END);
long fileLength=ftell(fp);
fseek(fp, fileLength-bufLength+1, SEEK_SET);
fread(&fileTag, sizeof(fileTag), 1, fp);
printf("%s\n", fileTag.tagMark);
return 0;
}
我正在使用一个文件对其进行测试,其中包含格式正确的id3标记。在id3标记中,前三个字节分别包含“T”,“A”和“G”,以便识别标记是否存在。有人知道为什么当我运行这个程序时,“_main”是打印出来的唯一东西吗?
答案 0 :(得分:5)
使用fseek()
(或lseek()
,如果您使用的是文件描述符而不是文件流),文件末尾带有负偏移(-128)字节。然后读取128字节的信息。
因此:
fseek(fp, -128L, SEEK_END);
lseek(fd, -128L, SEEK_END);
(有趣的是,SEEK_END
,SEEK_SET
和SEEK_CUR
宏都在标准C的<stdio.h>
和POSIX的<unistd.h>
中定义。)
答案 1 :(得分:4)
你的程序
fp=fopen(argv[0], "r+b");
argv [0]包含正在运行的可执行文件的名称,您希望argv[1]
是第一个命令行参数。您可能遇到的下一个问题(从ID3v2开始)是结构字段对齐,根据使用的数据类型,编译器可能在结构的连续成员之间留下“间隙”。为了避免这个问题,应该指示编译器在字节边界上对齐结构(在大多数情况下,检查编译器的文档)
#pragma pack(1)
这个Structure padding and packing SO答案清楚地解释了如果你不使用正确的包装会发生什么。
另外,请参阅the ID3V1 layout,各个字段后并不总是终止0,所以
printf("%s\n", fileTag.tagMark);
将打印TAG,然后打印歌曲标题(printf%s仅在遇到\ 0时停止。)
恕我直言,鉴于丛林中的ID3,你可能最好将原始ID3操作委托给现有的库id3lib,并专注于编辑器的功能。