c++如何实现一个简单的二进制文件内容对比差异展示工具【进阶】

星明同学_9433

星明同学_9433

2026-04-05

601人浏览

原创

应分块读取大文件以避免内存爆炸,使用64KB/128KB缓冲区,检查fread返回值,对齐起始位置后逐块比较,定位并输出十六进制偏移及字节级差异(如0x1A2F: 0x3C vs 0x3E),妥善处理EOF与长度不等情形,可选mmap加速但需fallback。

c++如何实现一个简单的二进制文件内容对比差异展示工具【进阶】

用 fread 逐块读取避免内存爆炸

直接把整个二进制文件 fread 进内存,对几百 MB 以上的文件就是灾难。实际工具必须分块读——常见做法是用 64KB 或 128KB 缓冲区(std::vector buf(65536)),每次读一块,对比一块。注意 fread 返回值可能小于请求长度(到 EOF 或 I/O 错误),必须检查,否则会把未初始化内存当有效数据比。

关键点:

  • 两个 FILE* 要用 fseek(fp, 0, SEEK_SET) 对齐起始位置再开始循环
  • 用 size_t n1 = fread(buf1.data(), 1, buf1.size(), fp1) 获取真实读入字节数
  • 只在 n1 == n2 且 n1 > 0 时 memcmp,否则按“一方提前结束”处理
  • 记录当前偏移量(offset += n1),用于后续定位差异位置

差异定位要输出十六进制偏移 + 字节级差异

用户真正需要的不是“不一样”,而是“哪里不一样、差成什么样”。所以不能只返回 bool,得输出类似:0x1A2F: 0x3C vs 0x3E。这意味着你得在 memcmp 失败后,遍历缓冲区找第一个不同字节索引,再换算成全局偏移(offset + i)。

实操建议:

  • 不要用 std::mismatch —— 它对原始字节无意义,且不保证返回首个差异点(取决于实现)
  • 手写循环:for (size_t i = 0; i
  • 输出格式统一用 printf("0x%zx: 0x%02x vs 0x%02x\n", diff_pos, buf1[i], buf2[i]),%02x 确保单字节补零
  • 一次只报前 10 个差异,加 --max-diff= 参数控制,防刷屏

处理文件长度不等的边界情况

memcmp 只能发现“同位置内容不同”,但无法捕获“A 文件还有剩余字节而 B 已结束”这类差异。这是二进制比对最常被忽略的坑。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

正确逻辑是:

  • 当 n1 != n2 时,说明至少一个文件已到 EOF;此时若 n1 > 0 && n2 == 0,则从 offset 开始所有剩余字节都算差异(A 多出内容)
  • 同样,n1 == 0 && n2 > 0 表示 B 多出内容
  • 必须单独处理这个分支,不能只依赖 memcmp 结果
  • 输出提示如:0x40000: A has extra 123 bytes,而不是静默跳过

用 mmap 加速大文件(Linux/macOS)但别盲目替换

mmap 对 >100MB 的文件确实更快,但代价是:Windows 没原生 mmap(得用 CreateFileMapping)、小文件反而更慢、内存占用不可控。进阶工具应该提供开关,而非默认启用。

若决定支持:

  • Linux 下用 open() + mmap() + munmap(),检查 MADV_RANDOM 是否可用
  • macOS 注意 MAP_FILE 已废弃,改用 MAP_ANONYMOUS 配合 read() 预加载
  • 务必 fallback 到 fread 方案:检测 mmap 失败(如 ENOMEM)时自动切回流式读取
  • 别忘了 msync —— 虽然只读场景不需要,但代码里留个注释提醒“若未来支持写入模式需同步”

真正的难点不在 memcmp,而在如何把“字节流差异”映射成用户可操作的信息:偏移是否对齐 sector?差异是否在 header 区域?这些得靠额外元数据或用户传参(比如 --header-size=512)来辅助判断。没这层,就只是个高级 cmp 命令而已。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

2023.06.20

948

5

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.28

1029

10

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

2025.10.15

3320

7

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

2025.10.24

867

6

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

2025.10.15

3320

7

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

2025.10.24

867

6

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.26

3479

3

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.27

3038

6

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

2023.08.01

1548

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习