核心是用 std::filesystem 扫描两目录,以 filename() 为键建哈希表配对同名文件;大小不同时直接标记 size mismatch,相同时再流式计算 xxHash 或 SHA-256 校验;输出需包含路径、大小、哈希值及缺失/多余状态。

用 std::filesystem 遍历目录并配对同名文件
核心是只比对「路径名相同」的文件,不关心嵌套层级是否一致。C++17 的 std::filesystem 可以递归遍历,但不会自动配对——得自己建索引。推荐先扫描基准目录(如 dir_a),把 path.filename() 作为 key、完整 path 作为 value 存进 std::unordered_map<:string std::filesystem::path>;再扫描目标目录(dir_b),对每个文件检查 map 中是否存在同名项。
注意点:
-
std::filesystem::path::filename()返回的是std::filesystem::path类型,比较时建议转成string()或直接用==(它已重载) - 大小写敏感:Windows 默认不区分,Linux/macOS 区分,若需跨平台一致行为,统一转小写再比较
- 跳过子目录:只处理
is_regular_file(),忽略is_directory()和符号链接(除非你明确要跟进)
选哪个哈希算法?std::hash 不行,得用 SHA-256 或 xxHash
std::hash 是为哈希表设计的,不是密码学安全哈希,碰撞概率高,且不保证跨进程/跨平台结果一致,绝对不能用于文件内容校验。
实际选型看需求:
- 要强一致性(比如发布包校验)→ 用
OpenSSL的SHA256()或libsodium的crypto_hash_sha256() - 纯性能优先(数万小文件)→ 用
xxHash(XXH3_64bits()),比 SHA-256 快 5–10 倍,碰撞率仍远低于实际风险阈值 - 不想引入第三方?C++23 的
和也帮不上忙,此时建议静态链接miniz(带简易 CRC32)或手撸一个 Fowler–Noll–Vo 变种(仅限测试场景)
示例(xxHash):
uint64_t hash = XXH3_64bits(file_data.data(), file_data.size());
大文件别全读进内存:用流式哈希 + 分块读取
直接 std::ifstream::read() 整个文件到 std::vector,遇到 2GB 文件就崩。必须分块(如 64KB)读取,每块喂给哈希更新函数。
关键操作顺序:
- 打开文件用
std::ios::binary模式,否则 Windows 下会误将\r\n转成\n - 用
std::ifstream::rdbuf()->sgetn()或循环read(),每次读固定 size,检查gcount()确认真实字节数 - xxHash 示例:
XXH3_state_t* state = XXH3_64bits_reset();<br>while (size_t n = input.read(buffer, sizeof(buffer)).gcount()) {<br> XXH3_64bits_update(state, buffer, n);<br>}<br>uint64_t final_hash = XXH3_64bits_digest(state);
比对结果怎么输出?别只打 "mismatch",要定位到具体文件
最常被忽略的是错误上下文。光说“哈希不一致”没用,得立刻知道是哪两个路径、各自哈希值、文件大小是否相同(大小不同说明根本不是同一份内容,不用算哈希)。
建议结构化输出(可重定向到日志):
- 先比大小:
file_a.size() != file_b.size()→ 直接标记为「size mismatch」,跳过哈希计算 - 大小相同但哈希不同 → 输出两行:
file_a: SHA256=... (size=12345)和file_b: SHA256=... (size=12345) - 只存在于一方的文件,单独归类为「missing in dir_b」或「extra in dir_b」,避免和内容差异混淆
哈希值建议用小写十六进制(std::hex ),方便后续用 sha256sum -c 验证。
真正麻烦的从来不是哈希本身,而是路径规范化、编码兼容性(比如 UTF-8 路径在旧 Windows API 下失效)、以及静默跳过权限不足的文件——这些地方不加 try/catch 或 std::filesystem::status() 检查,程序就卡死或漏比对。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











