使用C从二进制文件中删除最后128个字节

时间:2011-09-22 23:02:12

标签: c struct io id3

我在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”是打印出来的唯一东西吗?

2 个答案:

答案 0 :(得分:5)

使用fseek()(或lseek(),如果您使用的是文件描述符而不是文件流),文件末尾带有负偏移(-128)字节。然后读取128字节的信息。

因此:

fseek(fp, -128L, SEEK_END);
lseek(fd, -128L, SEEK_END);

(有趣的是,SEEK_ENDSEEK_SETSEEK_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,并专注于编辑器的功能。

相关问题