编辑大型二进制文件

本文关键字:二进制文件 大型 编辑 | 更新日期: 2023-09-27 18:12:39

我正忙于一个小项目,它有很多数据,比如图像、文本文件和其他东西,我想把它们都打包在一个或多个大文件中,这样程序文件夹就不会看起来凌乱。

但问题是我如何编辑这些文件。我已经考虑过文件结构它应该是这样的:

<>之前[DWORD]文件数[字]文件标识[STRING]文件名[字]文件大小[字]FileIndex[BYTES]所有文件之前

所以第一部分是太快得到所有文件的列表,FileIndex是二进制文件中的位置,所以我可以设置指针,例如300,并读取文件。

但是如果我想创建一个补丁并编辑它,我将不得不读取我正在编辑的文件后的所有字节,并将它们全部复制回来,这可能需要几个文件的时间。

当所有文件都插入时,二进制文件可能有几个100mb。

那么其他程序是如何做到这一点的,比如游戏使用这些大文件,也打了很多补丁,有没有什么技巧可以更快地插入额外的字节?

编辑大型二进制文件

在文件中间插入字节没有什么"技巧"。

通常的解决方案包括在文件末尾添加文件,然后切换它们在索引中的位置。然后你就会遇到必须整理文件碎片的问题。您可以将文件分成大块,这可以减轻碎片整理的一些麻烦,但这样文件就不是连续的。

如果您正在处理非静态数据,我不建议您这样做,除非您绝对必须这样做。我曾见过一些非常出色的软件工程师花了相当多的时间来编写一个合理的实现。

使用sqlite作为虚拟文件系统可能是一个可行的解决方案。但话又说回来,把数据文件放到另一个文件夹里,这样看起来就不会"凌乱"了。

如果可能的话,我可能会将数据打包到一个zip文件中。这不仅可以清理您的目录,而且(特别是对于您提到的文本文件)基本上可以免费进行一些压缩。当然,也有相当多的现有工具和库用于创建、检查、修改等zip文件。

使用zlib(举个例子),大多数工作都是为您处理的(例如,minizip中所演示的)。

诀窍是通过覆盖数据来制作补丁。否则,有一些系统可用于管理大量数据,例如数据库。

你可以创建一个数据库文件,将你的程序,并保存所有的数据在那里,而不是在文件。你甚至可以在应用程序中嵌入数据库代码,例如SQLite,或者使用外部数据库,如Sql Server, Oracle Sql或MySql。

你描述的基本上是实现你自己的文件系统。这是一项非常棘手和困难的任务,使其有效。

您可以将打包和编辑程序视为自定义内存分配器:

  1. 使用最小块大小-当您添加文件时,使用足够的整体块以适合文件。这将自动为文件提供一些空间生长:生长而不影响其它的
  2. 当一个文件变得太大,其当前分配,将其移动到包的末尾。
  3. 将空闲块标记为空闲,并保持偏移量到包头中的空闲列表。添加其他文件时,首先检查是否有足够大的空闲块。
  4. 当扩展文件超过当前块时,检查以下块是否在空闲列表中。
  5. 如果空闲列表太长(太多碎片),合并包。将每个文件向前移动,从第一个空闲块开始。这将不得不重写整个文件,但很少发生。

或者,不要使用您所拥有的简单目录,而是使用类似FAT的目录。对于每个文件,存储一个块和大小列表。当您扩展文件超过其当前分配时,将剩余部分添加到另一个块中。根据需要偶尔进行碎片整理。

这两种方法都会给包增加一点开销,但是留下空白确实是在每次插入时重写整个内容的唯一替代方法。

不能字节插入到您所描述的文件之外的文件中。这与编程语言无关。文件系统就是这样工作的…

您可以覆盖文件的部分,但前提是要尊重字节数。

您考虑过使用。zip文件吗?我经常看到一些格式将多个文件存储为一个文件,而底层文件实际上是一个zip文件。这样做的好处是zip库为您处理低级的位跟踪。

想到的几个例子:

  • 一个Word .docx文件实际上是一个zip(重命名为。zip,你可以打开它-它包含整个文件夹)
  • Silverlight包使用的。xap文件是另一个。

您可以使用托管共享内存,由内存映射文件支持。您仍然需要为整个文件提供足够的地址空间,但不需要将整个文件复制到内存中。您可以使用共享内存分配器的大多数标准工具,不过您很快就会发现,在任何地方指定自定义分配器是件麻烦事。但好消息是,您不需要自己实现所有这些,您可以使用Boost。,它已经具备了unix和windows所需的所有功能。