C风格的字符串文件格式难题

时间:2009-10-18 14:26:31

标签: c string data-structures file-format null-terminated

我对这个小问题非常困惑。我有一个非索引文件格式标头。 (更具体地说,ID3标头)现在,这个标头存储一个字符串或者说三个字节用于构造,数据实际上是一个ID3标签(TAG是字符串btw。)点是,现在这个{{1}在文件格式中不以null结尾。所以有两件事可以做:

  • 使用TAG加载整个文件,对于非终止字符串比较,请使用fread。但:
    1. 这听起来很讨厌
    2. 如果有人打开它并试图操作字符串而不知道这件事怎么办?
  • 另一个选项是加载文件,但C结构不应完全映射到文件格式,但应包含正确的空终止符,然后应使用唯一调用加载每个成员。但是,这也让人感觉很乱,而且很乏味。

非常感谢帮助,特别是那些具有处理此类东西的实践经验的人。

5 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

如果你刚学的东西,你可以通过读取文件的最后128个字节找到MP3文件中的ID3v1标签,并检查该块的前3个字符是否为TAG

对于实际应用,请使用TagLib

答案 2 :(得分:2)

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

对于此示例,strncmp()可以。通常,memcmp()更好,因为它不必担心字符串终止,因此即使您要比较的字节流(标记)包含ASCII NUL'\ 0'字符,memcmp()也可以。< / p>

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

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


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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

不要忘记id3 v1和id3v1.1

上两种不同含义的流派