20

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

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

实施必须相对较快,并且可以处理大量文件。它应该展示 O(n) 或 O(logn) 运行时。

我自己的算法要么很糟糕(快速但产生巨大的补丁),要么很慢(产生小补丁但运行时间为 O(n^2))。

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

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

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

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

这有点像压缩,没有开窗,所以会占用大量内存。但是,只要我尝试使代码输出最小化,它就相当快,并且会产生很小的补丁。

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

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


编辑#1:这是对上述算法的更详细描述。

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

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

第三,从新文件开始的地方开始循环,尝试定位现有的 4 个字节组合,并找到最长的匹配项。确保我们只考虑旧文件中的位置,或者新文件中比我们当前所在位置更早的位置。这确保了我们可以在补丁应用期间重用旧文件和新文件中的材料。


编辑#2上述算法的源代码

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

源代码使用了我库的其余部分中的许多其他类型,因此该文件并不是它所需要的全部,但这就是算法实现。


@lomaxx,我试图为 subversion 中使用的算法找到一个很好的文档,称为 xdelta,但除非您已经知道该算法是如何工作的,否则我找到的文档无法告诉我我需要知道什么。

或者也许我只是很密集...... :)

我从您提供的那个站点快速浏览了算法,不幸的是它不可用。来自二进制差异文件的评论说:

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

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

不过,感谢您的回答,如果我需要的话,可以在他的实用程序中添加一个书签。

编辑#1:注意,我会查看他的代码,看看我是否能找到一些想法,稍后我还会向他发送一封电子邮件,提出问题,但我已经阅读了他引用的那本书,尽管解决方案对找到最佳解决方案,由于时间要求,它在使用中是不切实际的。

编辑#2:我肯定会寻找 python xdelta 实现。

4

6 回答 6

5

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

于 2008-08-08T13:03:06.197 回答
4

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

最初的实现是用 C 语言实现的,但是这里描述了一个 C# 端口并且可以在此处获得。

于 2010-12-30T00:07:06.207 回答
3

你看过VCDiff吗?它是看起来相当活跃的 Misc 库的一部分(最新版本 r259,2008 年 4 月 23 日)。我没用过,但觉得值得一提。

于 2008-09-06T21:10:09.710 回答
1

可能值得看看其他一些人在这个领域所做的事情,也不一定是在 C# 领域。

这是一个用 c# 编写的库

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

于 2008-08-08T12:48:09.753 回答
1

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

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

于 2008-08-08T18:26:45.793 回答
0

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

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

于 2009-05-04T20:40:18.110 回答