c++ - 读取二进制文件 - 什么把二进制数据文件的头




c二进制文件读写 (8)

@rstevens说'文件类型的标识符'...合理的建议。 传统上,这就是所谓的幻数,在一个文件中,不是一个滥用术语(不像在代码中,这是一个滥用的术语)。 基本上,它是一些数字 - 通常至少4个字节,我通常确保至少有一个这些字节不是ASCII - 你可以用它来验证文件是你期望的类型,很可能被混淆。 您也可以在/ etc / magic(或本地等价物)中编写一个规则来报告包含您的幻数的文件是您的特殊文件类型。

你应该包含一个文件格式的版本号。 不过,我会建议不要使用代码的SVN号码。 当文件格式不正确时,您的代码可能会更改。

我有一个模拟,可以读取我们创建的大型二进制数据文件(10s到100s的GB)。 我们使用二进制速度的原因。 这些文件是依赖于系统的,从我们运行的每个系统上的文本文件转换而来,所以我不关心可移植性。 目前的文件是用fwrite编写的POD结构的许多实例。

我需要更改结构,所以我想添加一个头文件,其中包含一个文件版本号,只要结构发生变化,这个头文件就会增加。 既然我正在这样做,我想添加一些其他的信息。 我在想结构的大小,字节顺序,也许创建二进制文件的代码的svn版本号。 还有什么可以添加吗?


如果它们很大,我会在文件的开头预留一个健壮的块(64K?),并以XML格式存储元数据,然后是文件结束符(Ctrl-Z用于DOS / Windows,ctrl-D for unix?)。 通过这种方式,您可以使用XML中广泛的工具集轻松检查和解析元数据。

否则,我会跟别人已经说过的一样:创建文件的时间戳,为其创建的机器的标识符,基本上任何你可以想到的用于诊断目的的东西。 理想情况下,你会包括结构格式本身的定义。 如果经常改变结构,维护正确版本的代码以阅读各种格式的旧数据文件是一件很痛苦的事情。

@ highpercomp提到的HDF5的一大优点就是你只要不必担心结构格式的变化,只要你有一些名称和数据类型的约定即可。 结构名称和数据类型都存储在文件本身,所以你可以吹C代码smithereens并没有关系,你仍然可以从HDF5文件检索数据。 它可以让你不用担心数据格式和数据结构 ,也就是说我不关心字节序列,这是HDF5的问题,但是我关心字段名称等等。

我喜欢HDF5的另一个原因是您可以选择使用压缩,这需要非常少量的时间,如果数据缓慢变化或大部分相同,除了少数几个有趣的闪烁点,您可以在存储空间中获得巨大的胜利。


如果稍后将其他结构写入二进制文件,那么文件类型的标识符将会很有用。 也许这可能是一个简短的字符串,所以你可以通过查看文件(通过十六进制编辑器)看到它包含的内容。


对于大文件,你可能想要添加数据定义,所以你的文件格式变成自我描述。


您可能会考虑将文件偏移量放在标题中的一个固定位置,这会告诉您实际数据从文件开始的位置。 这将允许您在需要时更改标题的大小。

在一些情况下,我把值0x12345678放到头文件中,这样我就可以检测到文件格式是否与正在处理它的机器的字节序相匹配。


除了模式版本控制所需的任何信息之外,如果要解决问题,请添加可能具有价值的详细信息。 例如:

  • 文件创建和更新的时间戳(如果适用)。
  • 从版本的版本字符串(理想情况下,你有一个版本字符串是自动增加每个'官方'建设...这是不同的文件架构版本)。
  • 创建该文件的系统的名称,以及可能与您的应用程序相关的其他统计信息

我们发现这非常有用,(a)在获取信息时,我们必须要求客户提供和(b)获得正确的信息 - 有多少客户报告他们正在运行不同版本的软件,资料索赔!


我的变化结合了Roddy和Jason S的方法。

总结 - 将格式化的文本元数据放在文件末尾,以确定其长度存储在别处。

1)将长度字段放在文件的开头,以便知道最后元数据的长度,而不是假定固定的长度。 这样,为了获取元数据,您只需读取固定长度的初始字段,然后从文件末尾获取元数据blob。

2)使用XML或YAML或JSON作为元数据。 如果元数据被附加到最后,这是特别有用/安全的,因为没有人阅读文件就会自动地认为它是所有的XML,因为它是从XML开始的。

这种方法的唯一缺点是当元数据增长的时候,你必须更新文件的头部和尾部,但是其他部分可能已经被更新了。 如果只是像上次访问日期那样更新琐事,那么元数据长度不会改变,所以只需要更新就地。


正如我在电信设备配置和固件升级方面的经验所显示的,你只需要从版本(头部的固定部分)开始就确实需要几个预定义字节(这很重要)。 其余的标题是可选的,通过指出正确的版本,你总是可以显示如何处理它。 这里最重要的是你最好在文件末尾放置“可变的”头部分。 如果您计划对标题进行操作而不修改文件内容本身。 这也简化了“追加”操作,它应该重新计算可变头部分。

很高兴有固定大小头的功能(在开始):

  • 常见的“长度”字段(包括标题)。
  • 像CRC32(包括标题)。

好吧,对于可变部分XML或头部中的一些漂亮的可扩展格式是个好主意,但是真的需要它吗? 我有很多ASN编码的经验...在大多数情况下,它的使用被超过。

那么,当你看一下RFC 2126 (第4.3章)中描述的TPKT格式时,你可能会有更多的理解。





binaryfiles