最可靠的方式是调用系统diff命令生成unified格式补丁;二进制文件必须用bsdiff或xdelta3;自研差分算法不现实,应直接集成成熟工具源码。

用 diff 生成标准文本补丁最可靠
直接在 C++ 里从头实现 diff 算法不现实,也没必要。真实项目中,diff 命令(GNU diffutils)是生成文本文件补丁的事实标准,输出格式(如 unified diff)被 patch、Git、CI 工具广泛支持。
你的 C++ 程序只需调用系统 diff 并捕获输出即可:
std::string cmd = "diff -u old.txt new.txt > patch.diff"; int result = std::system(cmd.c_str());
注意点:
-
-u是关键参数,生成可读、可逆、工具兼容性最好的 unified 格式;不用-c或-e - 确保
old.txt和new.txt路径不含空格或 shell 特殊字符,否则需转义或改用posix_spawn+exec安全调用 - Windows 下需安装 Git for Windows 或 MSYS2 提供的
diff,原生 cmd 没有等效命令
二进制文件补丁必须用 bsdiff 或 xdelta3
diff 对二进制文件(如图片、可执行文件)基本无效——它按行比较,而二进制文件没有“行”概念,微小改动会导致后续全部错位。这时必须用专为二进制设计的差分工具。
推荐方案:
-
bsdiff(配对bspatch):压缩率高,适合固件/资源包更新,但内存占用大;C++ 可直接集成其 C 源码(仅两个 .c 文件) -
xdelta3:平衡速度与压缩比,支持流式处理,命令行易用:xdelta3 -e -s old.bin new.bin patch.xdelta - 别用
diff -a强制文本模式——生成的补丁体积暴增且不可靠
C++ 调用补丁工具时权限和路径容易出错
常见失败不是逻辑问题,而是环境没配好:
- Linux/macOS:确保
diff、xdelta3在$PATH中,或硬编码绝对路径(如/usr/bin/diff),避免依赖用户环境 - Windows:调用
xdelta3.exe前检查当前工作目录(GetCurrentDirectory),相对路径极易失效;建议用GetModuleFileName定位 exe 所在目录再拼接工具路径 - 所有工具调用后必须检查返回值:
std::system返回的是 shell 退出码,0成功,非0表示失败(如文件不存在、权限不足、工具未找到)
自研二进制差分算法极难达到实用水平
有人想用 C++ 写 VCDIFF 或 RSYNC 风格的滑动窗口匹配——理论上可行,但实际会卡在几个硬伤上:
- 内存爆炸:为找最长公共子串,朴素实现需要 O(n²) 空间,100MB 文件直接吃光 32GB 内存
- 速度瓶颈:
bsdiff的改进版 bsdiff4 用了后缀数组(SA-IS 算法),你重写一遍调试成本远超集成现成库 - 补丁验证缺失:生成的 patch 必须能用对应工具无损还原,自研代码很难覆盖所有 corner case(比如空文件、全零块、边界对齐)
真正要控制依赖时,直接把 bsdiff.c 和 bspatch.c 编进项目,比自己造轮子省三个月。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











