设计(二进制)文件格式时有哪些重点?

oli*_*ver 43 binary file-format

在设计用于记录二进制数据的文件格式时,您认为该格式应具有哪些属性?到目前为止,我已经提出了以下要点:

  • 在开头有一些"魔术字节",以便能够识别文件(在我的具体情况下,这也应该有助于区分文件与"遗留"文件)
  • 在开头有一个文件版本号,以便以后可以更改文件格式而不会破坏兼容性
  • 指定所有数据项的字节顺序和大小; 或者:包含一些空间来描述数据的字节顺序/大小(我倾向于前者)
  • 可能为将来可能需要的进一步的每个文件属性保留一些空间?

还有什么方法可以使这种格式更具有前瞻性,并最大限度地减少未来的麻烦?

Ste*_*rov 25

看看PNG规范.这种格式背后有一些非常好的理由.

此外,确定对您未来格式的重要性:紧凑性,兼容性,允许在其中嵌入其他格式(不同的压缩算法).另一个有趣的例子是Google的协议缓冲区,其中传输数据的大小是王者.

至于字节顺序,我建议你选择一个选项并坚持下去,不允许不同的字节顺序.否则,读写库只会变得更加复杂和缓慢.


Bar*_*art 16

我同意这些都是好主意:

  1. 一开始的魔术数字.在*nix中非常需要:

  2. 用于向后兼容的文件版本号.

  3. 字节顺序规范.

但是你的第四个是矫枉过正,因为#2允许你添加字段,只要你更改版本号(并且只要你不需要向前兼容).

  • 可能为将来可能需要的进一步的每个文件属性保留一些空间?

此外,在您的文件征收块结构的想法,在很多其他的答案中表达,似乎不太喜欢比解决一个问题,某些类型的有效载荷的二进制文件的通用要求.

除了以上1-3之外,我还要添加以下内容:

  • 简单的校验和或检测内容完整的其他方式.否则,您无法信任魔术字节或版本号.请注意规范校验和中包含哪些字节.通常,您将在文件中包含尚未进行错误检测的所有字节.

  • 您编写文件的软件版本(包括您拥有的最精细数字,例​​如内部版本号).你将得到一个错误报告,其中包含一个无法打开它的人的附件,他们在编写文件时没有任何线索,因为那时没有发生错误.但是错误是在编写它的版本中,而不是在试图阅读它的版本中.

  • 在规范中明确指出这是一种二进制格式,即所有字节都允许所有值0-255(幻数除外).

以下是一些可选的:

  • 如果你确实需要向前兼容性,你需要某种方式来表达哪些"块"是"可选的"(比如png),这样你以前的软件版本就可以优雅地跳过它们.

  • 如果您希望"在野外"找到这些文件,您可以考虑嵌入一些线索来查找规范.想象一下在png文件中找到字符串http://www.w3.org/TR/PNG/会有多大帮助.


atz*_*tzz 10

当然,这完全取决于格式的目的.

一种灵活的方法是将整个文件构造为TLV(Tag-Length-Value)三元组.例如,使您的文件由记录组成,每个记录以4字节标题开头:

1 byte  = record type
3 bytes = record length
followed by record content
Run Code Online (Sandbox Code Playgroud)

关于字节顺序,如果在文件中存储字节顺序指示符,则所有应用程序都必须支持所有字节顺序格式.另一方面,如果为文件指定特定的字节序,则只有具有不匹配的endiannes的平台上的应用程序才能执行其他工作,并且可以在编译时决定(使用条件编译).


小智 7

另一点,取自.xz文件规范(http://tukaani.org/xz/xz-file-format.txt):前几个字节之一应该是非字符,"以防止应用程序错误检测文件作为文本文件." 请注意编辑器和其他工具通常会检查多少个头字节,但在前四个或八个字节中使用非二进制字节似乎很有用.


Kev*_*Cox 5

在开始之前要了解的最重要的事情之一是如何使用您的文件。

  • 随机访问还是顺序访问会成为常态?
  • 多久读取一次数据?
  • 数据多久写入一次?
  • 您会一次性写出文件,还是会随着数据进入而减慢写入速度。
  • 文件需要可移植吗?并非所有格式都需要如此。
  • 是否需要兼容其他版本?也许更新文件就足够了。
  • 它需要易于读/写吗?
  • 大小/速度/复杂性权衡。

这里的大多数答案都在可移植性/兼容性方面提供了很好的建议,因此我不打算添加更多内容。但请考虑以下(经常被忽视的)事情。

  • 有些文件经常被写入而很少被读取(备份、日志等),您可能需要关注文件大小和易于写入。
  • 如果您的文件永远不会离开主机,或者很少离开主机,则转换字节序的速度会很慢(相对而言),因此转换是一个不错的选择,您可以获得显着的性能提升。考虑在标头中写入一个数字(例如 0x1234),以便您可以检测(并指示用户进行转换)是否是这种情况。
  • 有时简单的阅读确实很有用。如果您正在处理日志或文本文档,请考虑一次性压缩所有内容,而不是逐个条目压缩,以便您可以查看zcat | strings文件并查看里面的内容。

有很多事情需要记住,设计一个好的格式需要大量的规划和远见。诸如zcating 文件和获取有用信息或使用本机整数带来的小性能提升之类的小事情可以给您的产品带来优势,但是您需要小心,不要为了获得它而牺牲一些重要的东西。