Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用C从二进制文件中提取最后128个字节_C_Struct_Io_Id3 - Fatal编程技术网

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

使用C从二进制文件中提取最后128个字节,c,struct,io,id3,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(

我正在用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”,以标识标记是否存在。有人知道为什么在我运行这个程序时,“\u main”是唯一打印出来的东西吗?

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

因此:

fseek(fp, -128L, SEEK_END);
lseek(fd, -128L, SEEK_END);
(有趣的是,
SEEK\u END
SEEK\u SET
SEEK\u CUR
宏在标准C的
和POSIX的
中都有定义。)

您的程序没有

fp=fopen(argv[0], "r+b");
argv[0]包含正在运行的可执行文件的名称,您需要第一个命令行参数
argv[1]
。您可能会遇到的下一个问题(从ID3v2开始)是结构字段对齐,这取决于所使用的数据类型,编译器可能会在结构的连续成员之间留下“间隙”。为避免此问题,应指示编译器将字节边界上的结构与对齐(在大多数情况下,请查看编译器的文档)

这个答案清楚地解释了如果你没有使用正确的包装会发生什么

此外,请参见,在各个字段之后并不总是有终止的0,因此

printf("%s\n", fileTag.tagMark);
将打印标记,后跟歌曲标题(printf%s仅在遇到\0时停止)


IMHO,考虑到ID3是一个丛林,你最好将原始的ID3操作委托给一个现有的库,比如,并专注于编辑器的功能。

你应该能够
seek(fp,-128,seek\u END)int
double
,那将是另一个问题。)@Jonathan“下一个问题”指的是ID3v2.x,OP也必须支持它才能使其程序有用,并且该类型具有多个数据类型的字段。对于给定的情况,id3v1是我唯一需要担心的版本。
printf("%s\n", fileTag.tagMark);