【问题标题】:How to read CSV file with newline and comma characters inside cells in C++如何在 C++ 中的单元格内读取带有换行符和逗号字符的 CSV 文件
【发布时间】:2017-07-04 07:01:53
【问题描述】:

我有一个 CSV 文件,其中包含带有换行符 ("\n") 和/或用双引号括起来的逗号的单元格。 当我使用 getline() 函数获取每一行时,它将单元格内的每一行视为 csv 文件的新行。此外,当使用 splitIntoVec 获取每一行的向量时,它会将单元格内的逗号视为新的向量元素。 我想将 csv 文件的内容存储到一个向量向量中,其中每一行都是其单元格内的字符串向量。

例如,对于以下 csv 文件内容

"Row 1 cell 1
 With break line","Row1 cell2, with comma"
"Row 2 cell 1
 With break line","Row2 cell2, with comma"
 Row 3 cell 1,Row3 cell 2

我得到了 4 个字符串向量的结果向量,其中第一个只有一个元素,第二个有 3 个元素。 这是我的代码:

vector<vector<string>> readFromCsv(string &fileName, char rowDelimiter = "\n", char colDelimiter = ",") {
    ifstream file(fileName); // declare file stream
    string value;
    vector<vector<string>> contentVec;
    vector<string> rowVec;
    string rowStr;
    while (getline(file, rowStr, rowDelimiter)) {
        rowVec = splitIntoVec(rowStr, colDelimiter);
        contentVec.push_back(rowVec);
    }

    return contentVec;
}

是否有任何其他功能(在诸如 boost 之类的库中)可用于解决这些问题?任何帮助,将不胜感激。

在 PHP 中,我通过 fgetcsv() 正确获取了 csv 文件的内容。 c++中是否有替代功能?

【问题讨论】:

  • 您要解析的不是 CSV。 CSV 语法由RFC4180 定义,文档的第一点声明:Each record is located on a separate line, delimited by a line break (CRLF).
  • 单元格内的双引号怎么样?
  • @SimoneCifani 我使用的 csv 文件是由 PHP 创建的。另外,我用 excel 和 Libreoffice 创建了逗号分隔的 csv 文件,结果还是一样。
  • @DAle 是的! :|。单元格可能包含双引号。但我忽略了这个案例以避免更复杂!

标签: c++ csv vector


【解决方案1】:

@Simone 在他的评论中已经说过它不是 CSV 文件。但是看到您的问题,您将需要动手并进行一些文本处理以将其分开。您可以读取字符串中的完整文件,然后使用循环或您认为合适的任何方式进一步分解它。为此,您需要跟踪遇到的 " 而只有当它不在双引号内时才遍历和中断。

例如,

(左撇号)“第 1 行单元格 1 带折线"(右撇号),"(左撇号)Row1 cell2,带逗号"(右撇号)

您必须使用索引或数字来跟踪打开和关闭双撇号,并且仅当在打开和关闭撇号之外找到“\n”时才换行。

如果您确定单元格中没有 ",您也可以使用正则表达式。

感谢@Alex 有用的链接,如果其他人面临同样的问题:http://mybyteofcode.blogspot.nl/2010/11/parse-csv-file-with-embedded-new-lines.html

【讨论】:

  • 感谢您的建议。是的,我想我最终必须自己进行解析:/!考虑到问题的普遍性,你知道像 Boost 这样的库中有什么函数可以解决问题吗?因为编辑器创建的每个逗号分隔的 csv 文件都有这种格式。
  • 您可以编写一次此函数并在需要解析时使用它;)我不确定 boost 是否具有任何此类功能。如果它没有,你可以在那里做出贡献,如果你能让它成为通用的。
  • 阅读本文。这应该会有所帮助。链接:mybyteofcode.blogspot.in/2010/02/…
  • @Aref 您可以决定如何使用 boost 进行标记。我以前不知道,但有可能。
  • 非常感谢,它成功了:)。我通过修改同一网站的以下链接使其工作:mybyteofcode.blogspot.nl/2010/11/…
【解决方案2】:

你必须通过" 完全分开,保持两种状态:内部"" 和外部。 ,EOL 根据状态有不同的含义。

您可以使用getline(file, rowStr, '"') 来读取直到" 的所有内容,但是您在记录中分离的逻辑会稍微复杂一些。如果允许数字不带引号,那就更复杂了。

【讨论】:

  • 感谢您的建议。但问题是,当一个单元格不包含特殊字符如 "\n" 和 "," 时,它没有用双引号 (") 括起来。我该如何处理这种情况?在 PHP 中,我正确地获取了内容fgetcsv() 的 csv 文件。我想知道为什么在 c++ 中没有替代方法!
猜你喜欢
  • 1970-01-01
  • 2015-02-07
  • 2016-06-08
  • 1970-01-01
  • 2023-01-18
  • 2023-03-05
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
相关资源
最近更新 更多