使用 istream 提取运算符进行 csv 解析:如何检测缺失的字段值?



我正在尝试使用istream <<(运算符(进行简单的csv(空格分隔值(解析。

我的文件 csv 文件格式如下所示:

文件.csv


/名称 | 价值 | 间隔 |

名称1 11 1

姓名2 22 2

姓名3 33 3


我的示例代码如下所示:

fstream fin
std::pair<std::string, struct>entry{};
/* handle empty file path */
if(confPath != nullptr)
{
fin.open(confPath,ios::in);
/* handled no file on the specified path */
if(fin)
{
//check if the file is empty
if(fin.peek() != std::ifstream::traits_type::eof())
{
while(fin >> entry.first)
{
/* Take care of comments, empty lines and spaces */
if(entry.first[0] != '#' && entry.first[0] != '/' && entry.first[0] != 'n')
{
/* Populate the structure with properties from the csv file */
fin >> entry.second.value >> entry.second.interval >> endl;
}
else
{
fin.ignore(256, 'n');
}
}
}
else
{
cout << "file is empty" << endl;
}
}
else
{
cout << "file does not exists" << endl;
}
}

我的代码在空行或注释或随机空格下工作得很好,但如果缺少其中一个值,它将失败。例如,在 name2 行中,如果缺少值 22,则提取运算符会将 2 解释为值,间隔将设置为 0,并且不会继续解析下一行。

我想知道是否存在一个简单的解决方法来检测csv文件中缺少的字段。对我来说,忽略缺少某些字段但解析继续进行以下行的那一行是可以的。

我已经查看了一些选项,例如istream::get,getline,gcount,peek,但我无法提出任何简单的解决方案。目前,我无法更改csv格式本身。

对于此类用例,最好:

  1. 逐行读取文件的内容。
  2. 处理每行以提取相关数据。

您的代码可以转换为:

// ------------------------------------------------------------------------------
bool isCommentLine(std::string const& line)
{
return (!line.empty() && (line[0] == '#' || line[0] = '/') );
}
bool isEmtpyLine(std::string const& line)
{
// This function can get more involved depending on how you define an emtpy line.
// E.g. you could say a line is an empty line if all it has are whitespace characters.
return line.emtpy();
}
bool canIgnoreLine(std::string const& line)
{
return ( isCommentLine(line) || isEmtpyLine(line) );
}
void processLine(std::string const& line)
{
if ( canIgnoreLine(line) )
{
return;
}
// Parse the contents of the line using a stringstream.
std::istringstream str(line);
// Such as ...
// struct what? That needs to be changed.
std::pair<std::string, struct> entry{};
if ( str >> entry.first >> entry.second.value >> entry.second.interval )
{
// Got all the values successfully.
// Use them
}
else
{
// Deal with the error.
}
}
// ------------------------------------------------------------------------------
fstream fin
/* handle empty file path */
if(confPath != nullptr)
{
fin.open(confPath,ios::in);
/* handled no file on the specified path */
if(fin)
{
std::string line;
while ( getline(fin, line) )
{
processLine(line)
}
}
else
{
cout << "file does not exists" << endl;
}
}

最新更新