在C++中解析大型文本文件
Parsing large text file in C++
我有一个~250k行的文本文件。每行包含由多个空格和可能的其他符号分隔的数据。我想逐行解析数据,从每行检索某些组件。
我编写了一个程序,用于打开输入文件和输出文件,逐行解析输入文件,将行分解为适当的标记,并以所需的格式重新构造新行并立即输出到输出文件中。
问题是,当我运行它时,它在解析 70 到 92k 行后停止。通过停顿,我的意思是程序仍在运行,但是它不处理任何内容,并且我的终端中的光标只是停留在那里并闪烁。通过使用愚蠢的调试(使用 cout),我检查了在第 92521 行周围它确实需要一行输入行(正确的行),但是它没有通过分解为标记并重建格式良好的行的部分并停止。
下面我附上相关的代码。我期待有人告诉我正在发生的事情,即为什么我的程序停滞不前以及我可以以什么方式解决这个问题。感谢您的关注!
#include <iostream>
#include <fstream>
#include <cstring>
#include <sstream>
int main(int argc, char** argv) {
std::ifstream inFile;
std::ofstream outFile;
std::string inDir("/home/marcin/jnp2/proj/data/oceny.txt");
std::string outDir("/home/marcin/jnp2/proj/data/ocenyout.txt");
outFile.open(outDir, std::ios::out | std::ios::app);
inFile.open(inDir, std::ios::in);
std::string line;
int i = 1;
while(std::getline(inFile, line, 'n')) {
//for(int i = 0; i < 251819; i++) { // 197858
//std::string line;
//std::getline(inFile, line, 'n');
//std::cout << "OK1" << std::endl;
if(i == 92520) {
int x;
std::cin >> x;
}
if(!line.empty() && line[0] != '-' && line[0] != 'K' && line[0] != 'S') {
//std::cout << line << std::endl;
std::istringstream iss(line);
std::string code, name, dyd_cycle, term, grade, person, tmp;
iss >> code;
std::size_t found;
do {
if(iss >> tmp) {
//iss >> tmp;
found = tmp.find("20");
if (found == std::string::npos)
if(name.empty())
name = tmp;
else
name = name + " " + tmp;
else
dyd_cycle = tmp;
} else
return 42;
} while (found == std::string::npos);
//std::cout << "OK2" << std::endl;
iss >> term;
iss >> grade >> person;
std::string formattedLine = code + ";" + name + ";" + dyd_cycle + ";" + term + ";" + grade + ";" + person;
outFile << formattedLine << std::endl;
}
//std::cout << "OK3" << std::endl;
std::cout << i++ << std::endl;
}
inFile.close();
outFile.close();
return 0;
}
编辑:最后一个输出停止在"1000-621MRB;Metody realizacji baz danych;2004/TL;3;2;LONG_CODE_THAT_IM_NOT_SUPPOSED_TO_SHOW"。
我还要提到,当我一点一点地做时,即前 50k 行,然后告诉程序(通过硬编码以跳过前 50k 行)从 50k+1 行等开始没有问题 - 我得到了我应该得到的确切输出。另一方面,当我告诉它每 50k 行关闭一次文件,重新打开它们并循环到输入文件的正确行时,我仍然遇到了同样的问题。
Edit2:我将其编译为调试并使用了 gdb - 在关键行号周围,它正确获得了行(欢呼),但卡在了 iss>> 代码上。我在 CLion 中使用调试器,所以它只是在一段时间后超时。
使用 cout 并不总是最好的调试方法,因为我发现它有时会使程序的终端/整体速度陷入困境。可以尝试使用断言或实际调试器(如 GDB)来调试程序。调试器将逐步完成代码,并准确显示幕后发生的事情。
我确实有一个错误的日期 - 检查"20"导致程序进入永恒循环。我要感谢pm100和George Sovetov指出这段代码具有潜在危险。我使用调试器来查找问题 - 我感谢开发人员和 pm100 建议这样做。多亏了 gudok,我使用了一个检查来查看 iss>> tmp 是否有效,这帮助我注意到我的循环会变得过于永恒。
我将修复代码并使用正则表达式来避免任何其他形式的此类错误(根据 knivil 的建议)。我还将使用""而不是 std::endl,这是 kchinger 提议的方式。谢谢大家的所有评论!:)
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 文本文件中的单词链表
- 有效地从文本文件中读取带有字符串索引的大型二维数组(矩阵)
- 如何在大型文本文件中对数字进行排序
- 在大型 JSON 文件中查找文本
- 占用过多内存的大型 (10Mb) 文本的后缀树
- 读取C++中的大型映射文本文件
- 解析大型文本文件并使用C++将其存储在树(二进制或 AVL)中
- 加载大型文本文件(50,000多行,〜8MB)会导致我的程序停止
- 试图解析保存为std::字符串的大型文本文件
- 正则表达式是否足以分析大型文本
- 在C++中解析大型文本文件
- 如何从一个大型文本文件读取到一个数组c++
- 如何从大型文本文件中选择行数
- 将大型数据文件拆分为多个小文件(文本格式)
- 从大型文本文件读取到Qt中的结构数组中
- 在C++中并行读取一个大型文本文件
- 大型输入文本文件,每行有两个数字,如何更快地输入
- 使用unordered_map删除两个大型文本文件中的重复项
- 在C++中将大型文本文件快速读取为一维结构