使用 C 从二进制文件中取出最后 128 个字节
我正在用 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”是唯一打印出来的东西吗?
I am making an id3 tag editor in C. I am having trouble figuring out how to pull the last 128 bytes off the end of the binary file in order to manipulate/printout the area where the id3 tag sits. Heres some code:
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;
}
I am using a file to test this with that contains a properly formatted id3 tag. In an id3 tag, the first three bytes contain 'T', 'A', and 'G' respectively in order to identify that the tag exists. Does someone know why when I run this program, "_main" is the only thing that prints out?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用
fseek()
(或lseek()
(如果您使用文件描述符而不是文件流),距离文件末尾有负偏移量 (-128) 字节。然后读取128字节的信息。因此:(
有趣的是,
SEEK_END
、SEEK_SET
和SEEK_CUR
宏均在
中定义对于标准 C,在
中用于 POSIX。)Use
fseek()
(orlseek()
if you're using file descriptors instead of file streams) with a negative offset (-128) bytes from the end of the file. Then read the 128 bytes of information.Hence:
(Interestingly, the
SEEK_END
,SEEK_SET
andSEEK_CUR
macros are defined in both<stdio.h>
for standard C and in<unistd.h>
for POSIX.)您的程序确实
argv[0] 包含正在运行的可执行文件的名称,您需要 argv[1],即第一个命令行参数。您可能会遇到的下一个问题(从 ID3v2 开始时)是结构字段对齐,根据所使用的数据类型,编译器可能会在结构的连续成员之间留下“间隙”。为了避免此问题,应指示编译器将字节边界上的结构与
此 结构填充和包装 所以答案清楚地解释了如果您不使用正确的包装会发生什么。
另外,请参阅ID3V1 布局,各个字段后面并不总是以 0 结尾, so
将打印 TAG,后跟歌曲标题(printf %s 仅在遇到 \0 时停止)。
恕我直言,考虑到 ID3 的丛林,您可能最好将原始 ID3 操作委托给现有的库,例如 id3lib 并专注于编辑器的功能。
Your program does
argv[0] contains the name of the running executable, you want
argv[1]
, the first command line parameter. The next problem you'll probably run into (when starting with ID3v2) is structure field alignment, depending on the datatypes used the compiler may leave "gaps" between the consecutive members of a structure. To avoid this problem the compiler should be instructed to align the structure on byte boundaries with (in most cases, check your compiler's documentation)This Structure padding and packing SO answer explains clearly what happens if you don't use the correct packing.
Also, see the ID3V1 layout, there's not always a terminating 0 after the individual fields, so
will print TAG followed by the song title (printf %s only stops when it encounters a \0).
IMHO, given the jungle that ID3 is you're probably better off delegating the raw ID3 manipulation to an existing library like id3lib and focus on the functionality of your editor.