【问题标题】:C++ trying to read in malformed CSV with erroneous commasC++ 尝试使用错误的逗号读取格式错误的 CSV
【发布时间】:2017-09-25 13:00:34
【问题描述】:

我正在尝试制作一个简单的 CSV 文件解析器,以将大量订单从订单系统传输到发票系统。问题是我正在下载的 CSV 有错误的逗号,有时会出现在名称字段中,因此这会导致整个过程中断。

公司 INSISTS 真的开始让我生气了,他们只是将收到的数据复制到 CSV 中,因此它是有效数据。

Excel 似乎可以正确解释这一点,或者至少将数据放在正确的字段中,但我的程序却没有。我在记事本++中打开了CSV,字符串周围没有引号,只是用逗号分隔的原始字符串。

这是我目前读取文件的方式。

  int main()
  {
    string t;
    getline(cin, t);
    string Output;
    string path = "in.csv";
    ifstream input(path);
    vstring readout;
    vstring contact, InvoiceNumber, InvoiceDate, DueDate, Description, Quantity, UnitAmount, AccountCode, TaxType, Currency, Allocator, test, Backup, AllocatorBackup;
    vector<int> read, add, total;
    if (input.is_open()) {
        for (string line; getline(input, line); ) {
            auto arr = explode(line, ',');
            contact.push_back(arr[7]); // Source site is the customer in this instance.
            InvoiceNumber.push_back(arr[0]); // OrderID will be invoice number
            InvoiceDate.push_back(arr[1]); // Perchase date
            DueDate.push_back(arr[1]); // Same as order date
            Description.push_back(arr[0]);
            Quantity.push_back(arr[0]);
            UnitAmount.push_back(arr[10]); // The Total
            AccountCode.push_back(arr[7]); // Will be set depending on other factors - But contains the site of perchase
            Currency.push_back(arr[11]); // EUR/GBP
            Allocator.push_back(arr[6]); // This will decide the VAT treatment normally. 
            AllocatorBackup.push_back(arr[5]); // This will decide VAT treatment if the column is off by one.
            Backup.push_back(arr[12]);
            TaxType = Currency;
        }
    }
      return 0;
  }

  vstring explode(string const & s, char delim) {
    vstring result;
    istringstream q(s);
    for (string token; getline(q, token, delim); ) {
        result.push_back(move(token));
    }
    return result;
  }

Vstring 是我创建的一个编译器宏,用于节省我经常输入向量的时间,所以它是一样的。

问题是当我遇到其中一个带有逗号的字段(通常是名称字段 [3])时,它会将所有内容推回一,因此帐户代码变为 [8] 等等。这是非常麻烦,因为很难判断天气是否我正在处理下一个字段中的正确数据或在某些情况下不处理。

那么两个问题:

1) 有什么简单的方法可以让我检测到这个异常并纠正我错过的问题吗?如果有效数据在预期的位置,我当然会尝试检查我的循环,但这变得混乱并且不能处理多个逗号。

2) 公司是否正确告诉我允许客户输入的逗号未经处理就进入此 CSV 是“预期行为”,还是他们完全误解了 CSV“标准”?

【问题讨论】:

  • 在有效的 CSV 中,当字段包含分隔符时,它应该被引用。你的数据也是这样吗?
  • 你似乎知道一行会有多少个字段,所以如果一个字段是唯一的问题,那么解析它之前的字段,然后向后解析它之后的字段,剩下的是您遗漏的字段。
  • @boxmein 不,遗憾的是没有这么简单的事情,逗号只是坐在数据中间,没有清晰的视觉方式来判断它是一个新字段还是只是数据。文件中根本没有引号。
  • 1 - 没有简单的方法,除非您知道哪些字段可能被损坏以及具体以何种方式损坏 2 - 公司错了。如果分隔符作为字段的一部分出现,则整个字段必须用引号括起来
  • @user3407675 - 你知道他们使用什么工具来生成 CSV 吗?因为显然他们的工具并没有按照他们应该的方式引用东西,这是你问题的根源。如果您了解他们的工具链是什么,或许您可以帮助他们更好地利用它。

标签: c++ csv


【解决方案1】:

退休忍者在 cmets 中提到,一个约束是首先解析“问题字段”任一侧的所有字段,然后将剩余数据放入问题字段。如果您知道哪个字段可能包含损坏,这是最好的方法。如果您不知道哪个字段可能被损坏,您仍然可以选择!

你知道的:

  1. 应存在的字段数

  2. 关于每个字段中的数据类型。

如果您对字段的类型进行编码(实现不同数据类型的类,因此您的字符串向量将成为 OrderID 或 Dates 或 Counts 或....的向量),您可以测试不同的串联(连接相邻的字段用逗号分隔)并根据有多少字段通过某些数据验证对其进行评分。然后,您选择数据的最佳评分解释。这将在流程中构建一些数据验证,并使一切变得更加健壮。

【讨论】:

  • 这听起来确实是个不错的选择,因为我也有机会过滤掉更多有毒/格式错误的数据,并确保我不会解析任何可能危险的内容并减少到处发送无效发票。我还没有想过以这种方式做这件事,我一直痴迷于试图从一个假设中弄清楚什么是哪里。谢谢。
【解决方案2】:

'csv' 的定义不是很好。有 standard 方式,其中 ',' 分隔列和 '\n' 行。有时使用 '"' 来处理字段内的这些符号。但 Excel 仅在涉及控制字符时才包含它们。

这里是来自 Wiki 的定义。

RFC 4180 形式化的 CSV。它定义了 MIME 类型“text/csv”,并且遵循其规则的 CSV 文件应该具有非常广泛的可移植性。其要求包括:

-以 (CR/LF) 字符结尾的 MS-DOS 样式的行(对于 最后一行)。

-一个可选的头记录(没有确定的方法来检测 是否存在,因此在导入时需要小心)。

-每条记录“应该”包含相同数量的逗号分隔字段。

-任何字段可以被引用(用双引号)。

- 应引用包含换行符、双引号或逗号的字段。 (如果 > 他们不是,文件可能无法正确处理)。

-字段中的(双)引号字符必须由两个(双)引号>字符表示。 Comma-separated values

请记住,Excel 在不同的系统/系统语言设置上具有不同的设置。可能是他们的 Excel 正确解析它,但在其他地方却不是。

例如,在德国等国家/地区有“;”用于分隔列。小数分隔符也不同。

1.5

1,5

千位分隔符也是如此。

1,000,000

1.000.000

1 000 000

现在,Excel 也有不同的 csv 导出设置,如 .csv(分隔值)、.csv(MACINTOSH)和 .csv(MS-DOS),所以我猜也可能存在差异。

现在对于您的问题,在我看来,他们对文件所做的事情并没有明显错误。但是您应该考虑与他们讨论(E)BNF。这里有一些链接:

BNF EBNF

这是一种由您决定的语法,并且具有明确的定义,代码应该没有问题。我知道客户可以阻止这样的事情,因为他们不想有额外的工作,但这只是最好的解决方案。如果你想在你的文件中使用'"',他们应该以某种方式为你提供。我不知道他们如何复制他们的数据,但它也应该是某种程序(我不认为他们手动这样做?),所以你的代码和他们的代码应该使用你和他们一起决定的相同的 (E)BNF。

【讨论】:

  • 据我所知,Macintosh 和 MS-DOS 设置只影响行尾,而不是实际字段。
  • 其实是关于制表符、换行符和其他字符(特殊字符)的,查了一下。如果有兴趣:support.office.com/en-gb/article/…
  • 我想现在看到这个问题。然而,他们不遵守普遍接受的模板系统似乎相当不成熟。我不相信他们会愿意接受这一点,因为他们拒绝只清理逗号,而且这是其他人常用的服务上的一个按钮。但是感谢您的澄清,至少我现在了解他们的立场(因此延伸我的立场)
  • 我知道这可能很困难。我和我的老板就这个话题进行了很长时间的讨论,因为他希望我们编写的 csv 文件能够在每台计算机(在任何国家)上工作,而无需用户做任何事情。最后,我也不得不以某种方式对其进行管理,但大多数情况下我会尝试使用干净的解决方案而不是变通方法。此外,即使使用上述解决方案也可能会出现错误,也许传达这一点可以说服他们合作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-17
  • 1970-01-01
  • 1970-01-01
  • 2013-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多