C#中的二进制补丁生成

时间:2008-08-08 12:22:08

标签: c# file patch

有没有人知道或者知道C#中的二进制补丁生成算法实现?

基本上,比较两个文件(指定 new ),并生成可用于升级文件的补丁文件与 new 文件具有相同的内容。

实现必须相对较快,并使用大文件。它应该表现出O(n)或O(logn)运行时。

我自己的算法往往是糟糕的(快速但产生巨大的补丁)或慢(产生小补丁但有O(n ^ 2)运行时)。

任何建议或实施指南都会很好。

具体来说,该实现将用于使我们拥有一台主服务器的各种大型数据文件保持服务器同步。当主服务器数据文件发生变化时,我们也需要更新几个异地服务器。

我所做的最天真的算法,仅适用于可以保存在内存中的文件,如下所示:

  1. 文件中获取前四个字节,将其称为
  2. 将这些字节添加到字典中,其中 key - >位置,其中位置是我抓住这4个字节的位置,0是以
  3. 开头的
  4. 跳过这四个字节中的第一个,抓取另外4个(3个重叠,1个),并以相同的方式添加到字典
  5. 文件
  6. 中的所有4字节块重复步骤1-3
  7. new 文件的开头,抓取4个字节,并尝试在字典中查找
  8. 如果找到,通过比较两个文件中的字节
  9. ,找到最长匹配(如果有)
  10. 文件中对该位置的引用进行编码,并跳过 new 文件中匹配的块
  11. 如果未找到,请从 new 文件中编码1个字节,然后跳过它
  12. new 文件
  13. 的其余部分重复步骤5-8

    这有点像压缩,没有窗口,因此会占用大量内存。然而,它是相当快的,并且产生非常小的补丁,只要我尝试使代码输出最小。

    更节省内存的算法使用窗口,但会产生更大的补丁文件。

    我在本文中跳过了上述算法的细微差别,但如有必要,我可以发布更多细节。但是,我确实觉得我需要一个不同的算法,所以改进上述算法可能不会让我足够远。


    编辑#1 :以下是对上述算法的更详细说明。

    首先,合并这两个文件,这样你就有了一个大文件。记住两个文件之间的切点。

    其次,执行抓取4个字节,并将其位置添加到字典步骤,以便整个文件中的所有内容。

    第三,从 new 文件开始的地方开始,尝试找到4字节的现有组合,并找到最长的匹配。确保我们只考虑旧文件中的位置,或新文件中先前的位置,而不是我们当前位于的位置。这确保了我们可以在补丁应用程序中重用旧文件和新文件中的材料。


    编辑#2 Source code to the above algorithm

    您可能会收到有关证书存在问题的警告。我不知道如何解决这个问题,因此暂时接受证书。

    源使用我库中其余部分的许多其他类型,因此文件并非全部,但这就是算法实现。


    @lomaxx,我试图为subversion中使用的算法找到一个很好的文档,叫做xdelta,但是除非你已经知道算法是如何工作的,否则我发现的文档无法告诉我需要知道的内容。

    或许我只是在密集......:)

    我快速浏览了你所提供的网站上的算法,遗憾的是它不可用。二进制diff文件中的注释说:

      

    找到一组最佳差异需要相对于输入大小的二次时间,因此它很快就会无法使用。

    我的需求并非最佳,所以我正在寻找更实用的解决方案。

    感谢您的回答,如果我需要,可以在他的工具中添加一个书签。

    编辑#1 :请注意,我会查看他的代码,看看我是否能找到一些想法,我稍后会向他发送一封电子邮件,但我已经读过他引用的书虽然解决方案有助于找到最佳解决方案,但由于时间要求,它在使用中是不切实际的。

    编辑#2 :我肯定会追捕python xdelta实现。

6 个答案:

答案 0 :(得分:4)

抱歉,我无法提供更多帮助。我肯定会继续关注xdelta,因为我已经多次使用它来生成600MB + ISO文件的高质量差异,这些文件是我们为分发我们的产品而生成的,并且表现非常好。

答案 1 :(得分:4)

bsdiff旨在为二进制文件创建非常小的补丁。如其页面所述,它需要max(17*n,9*n+m)+O(1)字节的内存,并在O((n+m) log n)时间内运行(其中n是旧文件的大小,m是大小的{{1}}新文件)。

最初的实现是在C中,但是C#端口被描述为here并且可用here

答案 2 :(得分:3)

你见过VCDiff吗?它是Misc库的一部分,似乎相当活跃(最新版本r259,2008年4月23日)。我没有用它,但认为值得一提。

答案 3 :(得分:1)

可能值得查看一些其他人在这个领域做的事情,而不一定是在C#竞技场。

This is a library written in c#

SVN也有二进制差异算法,我知道python中有一个实现,虽然我用快速搜索找不到它。他们可能会给你一些关于在哪里改进自己的算法的想法

答案 4 :(得分:1)

如果这是用于安装或分发,您是否考虑过使用Windows Installer SDK?它能够修补二进制文件。

http://msdn.microsoft.com/en-us/library/aa370578(VS.85).aspx

答案 5 :(得分:0)

这是一个粗略的准则,但以下是可用于创建二进制补丁的rsync算法。

http://rsync.samba.org/tech_report/tech_report.html