【问题标题】:csv parsing with istream extraction operator: How to detect missing field values?使用 istream 提取运算符解析 csv:如何检测缺失的字段值?
【发布时间】:2019-10-10 21:44:27
【问题描述】:

我正在尝试使用 istream

我的文件 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;
    }
}

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

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

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

【问题讨论】:

    标签: c++ csv fstream istream extraction-operator


    【解决方案1】:

    对于此类用例,最好:

    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;
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-09
      • 1970-01-01
      • 2010-11-19
      • 2010-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-01
      相关资源
      最近更新 更多