如何创建二进制补丁?

Mik*_*ike 55 binary patch

为二进制文件制作补丁的最佳方法是什么?我希望用户应用它很简单(一个简单的patch应用程序会很好).在文件上运行diff只是给出了Binary files [...] differ

Hei*_*nzi 49

退房bsdiffbspatch(网站,手册,纸张,GitHub分叉).

要安装此工具:

  • Windows:下载并解压缩此软件包.你还需要一份bzip2.exein PATH; 从这里的"二进制"链接下载.
  • macOS:安装Homebrew并使用它进行安装bsdiff.
  • Linux:使用包管理器进行安装bsdiff.

  • 相当古老的来源.使用现代Visual Studio进行编译并不容易 - 使用VS 2009它已经有效,但是我在新版本中遇到了错误.此外它只有32位 - 这是一个关于内存消耗的真正问题(见其他答案).我不确定,如果仅使用x64编译修复此问题 - 我切换到.NET端口,请参阅其他答案. (2认同)

Max*_*kin 20

谷歌Chrome团队的Courgette看起来是二进制修补可执行文件的最有效工具.

引用他们的数据:

以下是开发人员频道上最近190.1 - > 190.4更新的大小:

  • 完整更新: 10,385,920字节
  • bsdiff更新: 704,512字节
  • 西葫芦更新: 78,848字节

以下是构建它的说明.这是2018年由Mehrdad提供的Windows二进制文件.

  • 文档说,"我们编写了一个新的diff算法,它更多地了解我们正在推送的数据类型 - 包含已编译可执行文件的大型文件".这意味着它对其他二进制文件不起作用(或者根本不行). (5认同)
  • 谢谢你的链接.但是在Windows下编译它是一个真实的故事.它首先安装一个完整的开发人员系统,例如Git,Python等.也许它可以工作,但在我的机器上,fetch使用了一些安全和失败的端口.有谁知道二进制下载链接? (2认同)
  • @James Courgette是bsdiff的真正继承者。来自文档:小胡瓜`diff = bsdiff(concat(原始的,猜测),更新)。使用合理的bdiff算法,您可以得到len(bdiff(concat(original,guess),update))<len(bdiff(original,update))+ C与一个小(常数)C。将“ C”设置为10是安全的选择。也许有人可以为bsdiff计算C。注意,如果给定的`bdiff`算法保证原始,随机和更新的任何值len(bdiff(concat(original,random),update))<= len(bdiff(original,update))`,则C == 1 。 (2认同)

Jar*_*eck 11

xdelta(网站,GitHub)是另一种选择.它似乎是最新的,但我不知道它与其他工具如bsdiff相比如何.

用法:

  • 创建补丁: xdelta -e -s old_file new_file delta_file
  • 应用补丁: xdelta -d -s old_file delta_file decoded_new_file

安装:

  • Windows:下载官方二进制文件.
  • 巧克力味: choco install xdelta3
  • 家酿: brew install xdelta
  • Linux:作为包管理器提供xdeltaxdelta3在包管理器中提供.


cjf*_*jfp 9

对于小而简单的补丁,最简单的方法是使用 -a (或 --text)选项告诉 diff 将文件视为文本。据我了解,更复杂的二进制差异仅对减少补丁的大小有用。

$ man diff | grep -B1 "as text"
       -a, --text
              treat all files as text
$ diff old new
Binary files old and new differ
$ diff -a old new > old.patch
$ patch < old.patch old
patching file old
$ diff old new
$
Run Code Online (Sandbox Code Playgroud)

如果文件大小相同且补丁仅修改几个字节,则可以使用 xxd,它通常随操作系统一起安装。以下将每个文件转换为每行一个字节的十六进制表示形式,然后比较文件以创建紧凑补丁,然后应用该补丁。

$ xxd -c1 old > old.hex
$ xxd -c1 new > new.hex
$ diff -u old.hex new.hex | grep "^+" | grep -v "^++" | sed "s/^+//" > old.hexpatch
$ xxd -c1 -r old.hexpatch old
$ diff old new
$
Run Code Online (Sandbox Code Playgroud)

对于支持进程替换的 shell(例如 bash 和 zsh),有一个更简单的方法可用:

$ comm -13 <(xxd -c1 old) <(xxd -c1 new) > old.hexpatch 
$ xxd -c1 -r old.hexpatch old
$ diff old new
$
Run Code Online (Sandbox Code Playgroud)

这里,comm -13 删除仅出现在第一个输入中的行以及出现在两个输入中的行,只留下第二个输入独有的行。


Phi*_*ilm 7

现代端口:bsdiff/bspatch非常有用的.NET端口:

https://github.com/LogosBible/bsdiff.net

我个人的选择.我测试了它,它是所有链接中唯一的,我可以开箱即用来编译它(使用Visual Studio,例如2013).(其他地方的C++源代码有点过时,至少需要一点抛光,只有32位设置实际内存(差异源大小)限制.这是这个C++代码bsdiff的一个端口,甚至测试补丁结果是否相同原始代码).

进一步的想法:使用.NET 4.5,您甚至可以摆脱#Zip lib,这是一个依赖.

我没有测量它是否比c ++代码略慢,但它对我来说很好,(bsdiff:1-2分钟内90 MB文件),对我来说时间关键只是bspatch,而不是bsdiff .

我不确定,如果使用x64机器的整个内存,但我认为它.支持x64的版本("任何CPU")至少可以工作.尝试使用100 MB文件.

- 此外:如果您的主要目标是可执行文件,引用的Google项目"Courgette"可能是最佳选择.但它是构建它的工作(对于Windows测量,至少),对于二进制文件,它也使用纯bsdiff/bspatch,据我所知的文档.