C++程序读取CSV文件仅能读取前三行无法完整读取问题求助
问题成因
- 循环条件使用错误:你采用
while(!inFile.eof())作为循环判断条件是典型的误用,eof()标记仅在尝试读取文件末尾失败后才会被置位,会导致最后一次循环大概率读取到空内容。同时你没有判断getline读取行的返回值,就算行读取失败也会强行解析旧的字符串内容,极易触发后续错误。 - 无字段校验与异常捕获:代码直接使用
stod、atoi对分割后的token做数值转换,未做任何有效性校验。如果某行存在字段缺失、数值格式错误(比如出现非数字字符),stod会直接抛出std::invalid_argument异常导致程序异常退出,表现为仅能读取到出错行之前的内容,你遇到的仅读前三行的问题大概率是第四行及之后的字段转换出错引发崩溃。 - 潜在边界问题:现有简单按逗号分割的逻辑无法处理字段本身带逗号(被双引号包裹)的CSV格式,一旦出现这类字段会导致后续字段错位,触发转换错误。
修复方案
- 修改循环逻辑,将
getline放入循环条件中,仅行读取成功才进入解析流程 - 增加字段读取校验、数值转换异常捕获逻辑,遇到错误行输出提示后直接跳过,避免程序崩溃
- 可选:针对带引号的CSV字段优化分割逻辑,适配更通用的CSV格式
修复后代码示例
void FilmDatabase::createDatabase (void) { string InputFile = "films2015.csv"; ifstream inFile(InputFile); if(!inFile) { cout << "File not found" << endl; return; } string inputString; // 逐行读取,读取成功才进入循环 while(getline(inFile, inputString)) { // 跳过空行 if(inputString.empty()) continue; istringstream iss1(inputString); string token; try { int rank= 0; string filmTitle = ""; string studio = ""; double totalGross = 0; int totalTheaters = 0; double openingGross = 0; int openingTheaters = 0; string openingDate = ""; // 读取每个字段都判断是否成功 if(!getline(iss1, token, ',')) throw runtime_error("缺失rank字段"); rank = stoi(token); if(!getline(iss1, token, ',')) throw runtime_error("缺失filmTitle字段"); filmTitle = token; if(!getline(iss1, token, ',')) throw runtime_error("缺失studio字段"); studio = token; if(!getline(iss1, token, ',')) throw runtime_error("缺失totalGross字段"); totalGross = stod(token); if(!getline(iss1, token, ',')) throw runtime_error("缺失totalTheaters字段"); totalTheaters = stoi(token); if(!getline(iss1, token, ',')) throw runtime_error("缺失openingGross字段"); openingGross = stod(token); if(!getline(iss1, token, ',')) throw runtime_error("缺失openingTheaters字段"); openingTheaters = stoi(token); if(!getline(iss1, token, ',')) throw runtime_error("缺失openingDate字段"); // 去除Windows换行残留的\r字符 if(!token.empty() && token.back() == '\r') token.pop_back(); openingDate = token; Film film(rank, filmTitle, studio, totalGross, totalTheaters, openingGross, openingTheaters, openingDate); film.printFilm(); filmDatabaseBST.add(film); } catch (const exception& e) { cout << "解析行失败:" << inputString << ",错误原因:" << e.what() << endl; // 跳过错误行继续处理下一行 continue; } } inFile.close(); }
运行修复后的代码如果出现解析失败的提示,可以直接定位到对应出错行,检查CSV内容是否存在格式错误即可。
内容的提问来源于stack exchange,提问作者EJBrawler
相关产品推荐
相关产品推荐

