-1

我正在尝试使用 istream <<(operator) 进行简单的 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 格式本身。

4

1 回答 1

0

对于此类用例,最好:

  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;
   }
}
于 2019-10-10T21:59:53.060 回答