C++ 和读取大文本文件
C++ and reading large txt files
我有很多txt文件,大约10GB。我应该在我的程序中使用什么来将它们合并到一个文件中而不重复?我想确保输出文件中的每一行都是唯一的。
我正在考虑制作某种哈希树并使用 MPI。我希望它有效。
如果您不需要保持低内存使用率,您可以将所有文件中的所有行读入 std::set
or std::unordered_set
。顾名思义,unordered_set
不以任何特定方式排序,而 set
是(字典排序顺序)。我在这里选择了 std::set
,但您可以尝试使用 std::unordered_set
看看是否可以加快速度。
示例:
#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>
#include <set>
#include <string>
#include <string_view>
#include <vector>
int cppmain(std::string_view program, std::vector<std::string_view> args) {
if(args.empty()) {
std::cerr << "USAGE: " << program << " files...\n";
return 1;
}
std::set<std::string> result; // to store all the unique lines
// loop over all the filenames the user supplied
for(auto& filename : args) {
// try to open the file
if(std::ifstream ifs(filename.data()); ifs) {
std::string line;
// read all lines and put them in the set:
while(std::getline(ifs, line)) result.insert(line);
} else {
std::cerr << filename << ": " << std::strerror(errno) << '\n';
return 1;
}
}
for(auto line : result) {
// ... manipulate the unique line here ...
std::cout << line << '\n'; // and print the result
}
return 0;
}
int main(int argc, char* argv[]) {
return cppmain(argv[0], {argv + 1, argv + argc});
}
- 构建 table 个文件,这样您就可以为每个文件名简单地指定一个数字(
std::vector<std::string>
就可以了)。
- 对于 table 中的每个文件:打开它,执行以下操作:
- 读一行。哈希行。
- 有一个
std::multimap
将行哈希(第 3 步)映射到 std::pair<uint32_t filenumber, size_t byte_start_of_line>
。如果你的新行哈希已经在哈希table中,打开指定文件,seek
到指定位置,检查你的新行和旧行是否相同或只是共享相同的哈希。
- 如果相同,则跳过;如果不同或尚不存在:向映射添加新条目,将行写入输出文件
- 阅读下一行(即转到第 3 步)
这只需要最长行所需的 RAM,加上足够的 RAM 用于文件名 + 文件编号加上开销,再加上映射的 space,这应该远少于实际行。由于 10GB 的文本并不多,因此发生哈希冲突的可能性相对较小,因此如果您不是在确定性之后,您也可以跳过“检查现有文件”部分,但所有行的概率都足够高在你的输出中。
我有很多txt文件,大约10GB。我应该在我的程序中使用什么来将它们合并到一个文件中而不重复?我想确保输出文件中的每一行都是唯一的。
我正在考虑制作某种哈希树并使用 MPI。我希望它有效。
如果您不需要保持低内存使用率,您可以将所有文件中的所有行读入 std::set
or std::unordered_set
。顾名思义,unordered_set
不以任何特定方式排序,而 set
是(字典排序顺序)。我在这里选择了 std::set
,但您可以尝试使用 std::unordered_set
看看是否可以加快速度。
示例:
#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>
#include <set>
#include <string>
#include <string_view>
#include <vector>
int cppmain(std::string_view program, std::vector<std::string_view> args) {
if(args.empty()) {
std::cerr << "USAGE: " << program << " files...\n";
return 1;
}
std::set<std::string> result; // to store all the unique lines
// loop over all the filenames the user supplied
for(auto& filename : args) {
// try to open the file
if(std::ifstream ifs(filename.data()); ifs) {
std::string line;
// read all lines and put them in the set:
while(std::getline(ifs, line)) result.insert(line);
} else {
std::cerr << filename << ": " << std::strerror(errno) << '\n';
return 1;
}
}
for(auto line : result) {
// ... manipulate the unique line here ...
std::cout << line << '\n'; // and print the result
}
return 0;
}
int main(int argc, char* argv[]) {
return cppmain(argv[0], {argv + 1, argv + argc});
}
- 构建 table 个文件,这样您就可以为每个文件名简单地指定一个数字(
std::vector<std::string>
就可以了)。 - 对于 table 中的每个文件:打开它,执行以下操作:
- 读一行。哈希行。
- 有一个
std::multimap
将行哈希(第 3 步)映射到std::pair<uint32_t filenumber, size_t byte_start_of_line>
。如果你的新行哈希已经在哈希table中,打开指定文件,seek
到指定位置,检查你的新行和旧行是否相同或只是共享相同的哈希。 - 如果相同,则跳过;如果不同或尚不存在:向映射添加新条目,将行写入输出文件
- 阅读下一行(即转到第 3 步)
这只需要最长行所需的 RAM,加上足够的 RAM 用于文件名 + 文件编号加上开销,再加上映射的 space,这应该远少于实际行。由于 10GB 的文本并不多,因此发生哈希冲突的可能性相对较小,因此如果您不是在确定性之后,您也可以跳过“检查现有文件”部分,但所有行的概率都足够高在你的输出中。