【问题标题】:How to perform line by line operation(some x) on a CSV file using c++如何使用c ++对CSV文件执行逐行操作(一些x)
【发布时间】:2016-03-26 19:57:42
【问题描述】:

我一直在为整行(\n 或 \r)的事情而苦苦挣扎,我被分配了一项任务来读取其中包含 4K 行的 .csv 文件。怀着好奇心,我找到了阅读的方法csv 文件并将每个字段/单词与分隔符 ',' 分开。

std::istream& safeGetline(std::istream& is, std::string& t)
{
    t.clear();
    std::istream::sentry se(is);
    std::streambuf* sb = is.rdbuf();

    for(;;) {
        int c = sb->sbumpc();
        switch (c) {
        case '\r':
            if(sb->sgetc() == '\n')
                sb->sbumpc();
            return is;
        case EOF:
            // Also handle the case when the last line has no line ending
            if(t.empty())
                is.setstate(std::ios::eofbit);
            return is;
        default:
            t += (char)c;
        }
    }
}

    int main()
    {
        cout<<"Enter the file path :";
        string filename;
        cin>>filename;
        ifstream file;
        file.open(filename.c_str(),ios::in);
        vector<string>arr;
        string content;
        string arr2;
        stringstream ss;
       // sqlite3 *db;int rc;sqlite3_stmt * stmt;
        int i=0;
         while (!safeGetline(file,content).eof())--here is the problem
        {
            ss<<content;
    //since some of the field content falls next line i have decided to remove the '\n'
            content.erase(std::remove(content.begin(), content.end(), '\n'), content.end());
            while (getline(ss,arr2,','))
            {
               arr.push_back(arr2);
            }
       }
}

这里是while (!safeGetline(file,content).eof())--我认为这段代码会从 CSV 文件中读取第一行并通过 while (getline(ss,arr2,',')) 进行分隔符分隔,但发生的情况是 safeGetline() 以及正常的 getline() --我之前尝试过而不是safeGetline() 读取整个内容并通过分隔符分隔部分,这让我很难在数据库中插入这些字段

例如:

4xxxxxx,"field2",field3,,,,field7
400x1x2,"field2",,field4,,,field7

代码开始读取后,while(!safeGetline(file,content).eof())返回

输出:

4xxxxxx,"field2",field3,,,,field7400x1x2,"field2",,field4,,,field7

这里的 field7 和第二行的值 400x1x2 组合在一起field7400x1x2--当我将这些字段插入我的表中时,这会产生虚假结果(即)值在表中不正确地混乱。

那么在我的情况下,我如何才能真正执行逐行读取操作(即)读取->单独分隔符->推送到矢量->插入表格->第二次读取->.....

【问题讨论】:

    标签: c++ sqlite csv c++11 getline


    【解决方案1】:

    您似乎希望将 CRLF 序列保留在原始输入中。从外观上看,您正在一个 Windows 系统上工作,其中以文本模式打开的 std::ifstream 将以将 CRLF 序列合并为单个 '\n' 字符的方式打开。文本和二进制模式之间的区别正是行尾序列的翻译或不存在。使用打开您的文件

    file.open(filename.c_str(), std::ios_base::in | std::ios_base::binary);
    

    请注意,常规方法是使用eof() 来指示读取失败。相反,std::ios_base::eofbit 将在流触及文件末尾时设置。使用std::ios_base::failbit 指示读取格式失败,读取循环的规范方法是:

    while (safeGetline(file, content)) {
       // ...
    }
    

    std::ios_base::failbitstd::ios_base::badbit 均未设置时,流将转换为true

    【讨论】:

      【解决方案2】:

      你的 switch 语句

          switch (c) {
          case '\r':
              if(sb->sgetc() == '\n')
                  sb->sbumpc();
              return is;
          case EOF:
              // Also handle the case when the last line has no line ending
              if(t.empty())
                  is.setstate(std::ios::eofbit);
              return is;
          default:
              t += (char)c;
          }
      

      仅检测 '\r' 或 '\r\n' 情况。它无法单独处理带有 '\n' 字符的文件。

      所以改成这样:

          case '\n':
          case '\r':
              if(sb->sgetc() == '\n' || sb->sgetc() == '\r')
                  sb->sbumpc();
              return is;
      

      【讨论】:

      • 我故意从函数中删除了这种情况:'\n',因为我的结束行表示 CRLF 并且 CSV 中的某些列或字段在其中包含 LF,我采取立场删除它,阅读没有问题---除了 getline() 或 safegetline() 一次读取整个数据..我已经丢失了我提到的序列
      猜你喜欢
      • 1970-01-01
      • 2014-08-12
      • 2016-09-13
      • 1970-01-01
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多