如何使用C++高效查找两个超大型文件中的重复行?
结论先行
C++完全可以轻松处理这个量级的任务,只要优化得当,整个流程耗时可以控制在几分钟甚至几十秒级别,远低于你之前遇到的30分钟的情况。你之前Python版本速度极慢,核心问题几乎可以肯定是实现逻辑错误,而非语言本身的性能上限。
核心优化思路
你此前的慢大概率是用了两层循环逐行对比的O(n²)逻辑,只要改成哈希匹配方案,哪怕是Python版本也能把耗时压缩到小时内,C++优化得当可以跑到分钟级。
第一步:优先用小文件构建哈希集合
1.5G共4000万行的小文件是更适合先加载的,就算每行平均长度40字节,全部存到哈希集合里内存占用也才1.6G上下,普通民用设备完全够装,不需要搞外部排序那么复杂的方案。
- 操作逻辑:先把小文件的所有行存进哈希集合,再逐行读取大文件,判断当前行是否在哈希集合中,存在就写入结果文件,整体时间复杂度是O(M+N)(M是小文件行数,N是大文件行数)
- C++优先用
absl::flat_hash_set存储,性能比标准库的std::unordered_set高30%以上
第二步:优化IO读写,减少系统调用
不管用什么语言,默认的逐行读很多时候缓冲区开得太小,会频繁触发系统调用导致速度骤降,优化点:
- 给文件流开足够大的缓冲区,比如设置16MB或者32MB的读缓存
- C++中先执行
ios::sync_with_stdio(false); cin.tie(nullptr);禁用stdio同步,能大幅提升iostream的读写速度 - 不要每行读完就马上写结果,凑够一定大小(比如几MB)再批量写进输出文件,不要用
endl换行,endl会强制刷新缓存,用'\n'代替
第三步:内存不足的兜底方案
如果设备内存吃紧不够存4000万行的哈希集合,可以用布隆过滤器先过滤一轮:先把小文件的行全部打进布隆过滤器,读大文件的时候先过布隆过滤器,不存在的直接跳过,存在的再做二次确认,内存占用可以降到几十MB,代价是多一轮小文件的二次读取,可以根据自身设备情况权衡。
C++实现的参考代码
#include <iostream> #include <fstream> #include <string> #include <memory> #include <absl/container/flat_hash_set.h> using namespace std; int main() { // 禁用stdio同步,大幅提升流读写速度 ios::sync_with_stdio(false); cin.tie(nullptr); // 配置32MB读写缓冲区 const size_t BUF_SIZE = 32 * 1024 * 1024; auto read_buf = make_unique<char[]>(BUF_SIZE); auto write_buf = make_unique<char[]>(BUF_SIZE); // 读取小文件构建哈希集合 ifstream small_file("small_file_path", ios::in); small_file.rdbuf()->pubsetbuf(read_buf.get(), BUF_SIZE); absl::flat_hash_set<string> small_line_set; string line; while (getline(small_file, line)) { small_line_set.insert(line); } small_file.close(); // 读取大文件对比输出重复行 ifstream large_file("large_file_path", ios::in); large_file.rdbuf()->pubsetbuf(read_buf.get(), BUF_SIZE); ofstream out_file("duplicate_result_path", ios::out); out_file.rdbuf()->pubsetbuf(write_buf.get(), BUF_SIZE); while (getline(large_file, line)) { if (small_line_set.contains(line)) { out_file << line << '\n'; } } return 0; }
额外注意事项
- 如果小文件本身存在大量重复行,可以先对小文件做一次去重,减少哈希集合的内存占用
- 注意处理换行符差异:如果两个文件的换行符不一致(比如一个是
\n一个是\r\n),读行的时候要提前统一处理,避免内容一致但判断为不相等的问题 - 不想写代码也可以直接用Linux自带命令行工具完成:
sort small.txt large.txt | uniq -d > duplicates.txt,不过排序大文件会用到临时磁盘空间,速度比哈希方案慢,但胜在零开发成本
内容的提问来源于stack exchange,提问作者Hje282
相关产品推荐
相关产品推荐

