0

我对我遇到的这个小问题感到非常困惑。我有一个非索引文件格式标题。(更具体地说是 ID3 标头)现在,此标头存储一个字符串,或者更确切地说是三个字节,以确认数据实际上是一个 ID3 标记(TAG顺便说一句是字符串)。重点是,现在TAG文件格式中的 this 不是以空值结尾的. 所以有两件事可以做:

  • 使用 和加载整个文件以fread进行非终止字符串比较,请使用strncmp. 但:
    1. 这听起来很骇人听闻
    2. 如果有人打开它并试图在没有先验知识的情况下操纵字符串怎么办?
  • 另一种选择是加载文件,但 C 结构不应该完全映射到文件格式,而是包含适当的空终止符,然后应该使用唯一的调用加载每个成员。但是,这也感觉很hacky并且很乏味。

非常感谢您的帮助,尤其是有处理此类问题的实际经验的人的帮助。

4

5 回答 5

3

解析任何内容时首先要考虑的是:这些字段的长度是固定大小还是以计数为前缀(它们本身的大小是固定的,例如,几乎每个图形文件都有一个固定大小/结构的标题,后跟一个可变大小的像素序列)?或者,格式是否具有以某种方式分隔的完全可变长度字段(例如,MPEG4 帧由字节 0x00、0x00、0x01 分隔)?通常,这个问题的答案将大大有助于告诉您如何解析它。

于 2009-10-18T14:53:59.697 回答
2

如果文件格式规范说某个三个字节的值对应于“T”、“A”、“G”(84、65、71),那么您应该只比较这三个字节。

对于这个例子,strncmp()是可以的。一般来说, memcmp() 更好,因为它不必担心字符串终止,因此即使您正在比较的字节流(标签)包含 ASCII NUL '\0' 字符,memcmp()也可以工作。

您还需要识别您使用的文件格式主要是可打印数据还是主要是二进制数据。用于可打印数据的技术可能与用于二进制数据的技术不同;用于二进制数据的技术有时(但并非总是)转换为用于可打印数据。一个很大的区别是二进制数据中值的长度是预先知道的,要么是因为长度嵌入在文件中,要么是因为文件的结构是已知的。对于可打印的数据,您通常会处理在字段上具有隐式边界的可变长度编码 - 并且前面没有长度编码信息。

例如,Unix 密码文件格式是具有可变长度字段的文本编码;它使用“:”来分隔字段。在遇到下一个“:”或行尾之前,您无法判断一个字段有多长。这需要与使用 ASN.1 1编码的二进制格式不同的处理方式,其中字段在实际数据之前可以有一个类型指示值(通常是一个字节)和一个长度(可以是 1、2 或 4 个字节,取决于类型)场。


1 ASN.1(有理由)被认为非常复杂;我给出了一个非常简单的例子,大致说明了它是如何使用的,可以在很多层面上受到批评。然而,基本思想是有效的——长度(对于 ASN.1,通常也是类型)在(二进制)数据之前。这也称为TLV - 类型、长度、值 - 编码。

于 2009-10-18T15:10:52.653 回答
2

如果您只是学习一些东西,您可以通过读取文件的最后 128 个字节并检查该块的前 3 个字符是否为 MP3 文件中的 ID3v1 标记TAG

对于真正的应用程序,请使用TagLib

于 2009-10-18T14:42:52.350 回答
1

保留三个字节并将每个字节与字符'T','A'和进行比较'G'。这可能不是很聪明,但可以很好地完成工作,更重要的是正确。

于 2009-10-18T14:29:27.250 回答
0

并且不要忘记 id3 v1 和 id3v1.1 上两种不同含义的类型

于 2009-10-19T23:40:41.743 回答