【问题标题】:Editing large binary files编辑大型二进制文件
【发布时间】:2011-10-27 17:14:57
【问题描述】:

我正忙于一个小项目,该项目包含大量数据,例如图像文本文件和其他内容,我正试图将它们全部打包到一个大文件或多个大文件中,这样程序文件夹看起来不乱七八糟的。

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

[DWORD] 文件数 [DWORD]文件ID [STRING]文件名 [DWORD]文件大小 [DWORD]文件索引 [BYTES]所有文件

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

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

插入所有文件后,二进制文件可能只有几百兆。

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

【问题讨论】:

  • 只是出于好奇,谁会查看您的程序目录并在意它看起来很乱?通常人们不需要关心你的程序目录。
  • 是的,你说得对,但我只是想提高我的编程技能并尝试不同的东西,现在我正在使用文件系统,我可以通过我自己

标签: c# c++ file


【解决方案1】:

在文件中间插入字节没有“技巧”。

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

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

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

【讨论】:

    【解决方案2】:

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

    使用zlib(例如),大部分工作都会为您处理(例如,如minizip 所示)。

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

        1. 使用最小块大小 - 添加文件时,使用足够的整体 块以适应文件。这会自动给文件一些空间 在不影响其他人的情况下成长。
        2. 当文件对于其当前分配来说太大时,将其移至包的末尾。
        3. 将空闲块标记为空闲,并将偏移量保留在块的头部 包头中的空闲列表。添加其他文件时,首先 检查是否有足够大的空闲块供他们使用。
        4. 将文件扩展至当前块之外时,请检查下一个块是否在空闲列表中。
        5. 如果空闲列表过长(碎片过多),请合并软件包。向前移动每个文件以从第一个空闲块开始。这将不得不重写整个文件,但这种情况很少发生。

        或者,使用FAT 之类的东西代替您拥有的简单目录。对于每个文件,存储块和大小的列表。当您将文件扩展超过其当前分配时,请添加另一个带有剩余部分的块。根据需要不时进行碎片整理。

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

        【讨论】:

        • 我也会自己分割文件以节省空间。
        【解决方案5】:

        不是将字节插入到您描述的文件以外的文件中的方法。这与编程语言无关。这就是文件系统的工作方式......

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

        【讨论】:

          【解决方案6】:

          您是否考虑过使用 .zip 文件?我一直在看到多个文件存储为一个的格式,而底层文件实际上是一个 zip 文件。这样做的好处是 zip 库为您处理低级位跟踪内容。

          想到的几个例子:

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

          【讨论】:

          • Java 的 .jar 文件使用 zip 程序打开,但根据我没有研究过的一些技术问题,它们技术上不是 zip。
          【解决方案7】:

          您可以使用受内存映射文件支持的托管共享内存。您仍然需要为整个文件提供足够的地址空间,但您不需要将整个文件复制到内存中。您可以将大多数标准工具与共享内存分配器一起使用,尽管您很快就会发现在任何地方指定自定义分配器是一件苦差事。但好消息是您不需要全部自己实现,您可以采用 Boost.Interprocess,它已经具备适用于 unix 和 windows 的所有必要功能。

          【讨论】:

            猜你喜欢
            • 2015-10-26
            • 2015-11-29
            • 2010-12-27
            • 2020-03-21
            • 2018-11-08
            • 2014-04-27
            • 1970-01-01
            • 1970-01-01
            • 2018-01-29
            相关资源
            最近更新 更多