请注意,我对基于意见的答案不感兴趣。
我知道的:
没有多少…一个是,这些错误很少显示测试数据,但在现实世界中不那么少。
另一个是,如所述,它们阻止正确解析CSV。认为很难用测试数据重现错误,我(可能)寻求帮助,谁已经尝试使用字符串列表作为生产代码中的CSV解析器。
不相关问题:
我获得了关于“Delphi-XE”标记问题的信息,因此由于“空格字符被视为分隔符”feature而导致的解析失败不适用。因为引入的StrictDelimiter
属性与Delphi 2006解决了。我,我自己,使用Delphi 2007。
此外,由于字符串列表只能保存字符串,它只负责拆分字段。涉及由于语言环境差异等引起的字段值(f.i.日期,浮点数字…)的任何转换难度不在范围内。
基本规则:
CSV没有标准规范。但有从various specifications推断的基本规则。
下面是TStringList如何处理这些的演示。规则和示例字符串来自Wikipedia.括号([])叠加在字符串周围,以便能够通过测试代码查看前导或尾随空格(如果相关)。
空格被视为字段的一部分,不应被忽略。
Test string: [1997,Ford,E350] Items: [1997] [ Ford ] [ E350]
带有内置逗号的字段必须用双引号字符括起来。
Test string: [1997,E350,"Super,luxurIoUs truck"] Items: [1997] [Ford] [E350] [Super,luxurIoUs truck]
具有嵌入的双引号字符的字段必须包含在双引号字符中,每个嵌入的双引号字符必须由一对双引号字符表示。
Test string: [1997,""luxurIoUs"" truck"] Items: [1997] [Ford] [E350] [Super,"luxurIoUs" truck]
具有嵌入换行符的字段必须括在双引号字符中。
Test string: [1997,"Go get one now they are going fast"] Items: [1997] [Ford] [E350] [Go get one now they are going fast]
在修改前导或尾随空格的CSV实施中,具有此类空格的字段必须括在双引号字符中。
Test string: [1997," Super luxurIoUs truck "] Items: [1997] [Ford] [E350] [ Super luxurIoUs truck ]
字段可以始终包含在双引号字符中,无论是否必需。
Test string: ["1997","Ford","E350"] Items: [1997] [Ford] [E350]
测试代码:
var SL: TStringList; rule: string; function GetItemsText: string; var i: Integer; begin for i := 0 to SL.Count - 1 do Result := Result + '[' + SL[i] + '] '; end; procedure Test(TestStr: string); begin SL.DelimitedText := TestStr; Writeln(rule + sLineBreak,'Test string: [',TestStr + ']' + sLineBreak,'Items: ' + GetItemsText + sLineBreak); end; begin SL := TStringList.Create; SL.Delimiter := ','; // default,but ";" is used with some locales SL.QuoteChar := '"'; // default SL.StrictDelimiter := True; // required: strings are separated *only* by Delimiter rule := 'Spaces are considered part of a field and should not be ignored.'; Test('1997,E350'); rule := 'Fields with embedded commas must be enclosed within double-quote characters.'; Test('1997,luxurIoUs truck"'); rule := 'Fields with embedded double-quote characters must be enclosed within double-quote characters,and each of the embedded double-quote characters must be represented by a pair of double-quote characters.'; Test('1997,""luxurIoUs"" truck"'); rule := 'Fields with embedded line breaks must be enclosed within double-quote characters.'; Test('1997,"Go get one now'#10#13'they are going fast"'); rule := 'In CSV implementations that trim leading or trailing spaces,fields with such spaces must be enclosed within double-quote characters.'; Test('1997," Super luxurIoUs truck "'); rule := 'Fields may always be enclosed within double-quote characters,whether necessary or not.'; Test('"1997","E350"'); SL.Free; end;
如果你已经读过这一切,问题是:),什么是“TStringList分裂错误?
解决方法
Not much… One is that,these bugs show up rarely with test data,but not so rarely in real world.
它只需一个案例。测试数据不是随机数据,一个用户有一个失败的情况应该提交数据和voilà,我们有一个测试用例。如果没有人能提供测试数据,也许没有错误/失败?
There’s no standard specification for CSV.
那一个肯定有助于混乱。没有标准规范,你如何证明什么是错的?如果这是由自己的直觉,你可能会遇到各种各样的麻烦。这里有一些从我自己与政府发布的软件的快乐互动;我的应用程序应该导出CSV格式的数据,政府的应用程序应该导入它。这是什么让我们连续几年的很多麻烦:
>如何表示空数据?由于没有CSV标准,一年我的友好的政府决定任何事情,包括没有(两个连续的逗号)。接下来他们决定只有连续的逗号就OK了,也就是Field,“”,字段无效,应该是Field,Field。有很多乐趣向我的客户解释,gov应用程序更改验证规则从一周到下一个…
>您导出零整数数据吗?这可能是一个更大的滥用,但我的“gov应用程序”决定也验证也。一次强制包含0,那么强制不包括0.也就是说,一次性Field,0,Field是有效的,下一个Field,Field是唯一有效的方式…
这里是另一个测试用例(我的)直觉失败:
1997,“Super,luxurIoUs truck”
请注意之间的空格,以及“超级,和随后的很幸运的逗号”超级。 TStrings使用的解析器只能看到quote char,如果它紧跟在分隔符之后。该字符串解析为:
[1997] [ Ford] [ E350] [ "Super] [ luxurIoUs truck"]
直觉我会期望:
[1997] [ Ford] [ E350] [Super luxurIoUs truck]
但猜猜什么,Excel它是同样的方式Delphi做它…
结论
> TStrings.CommaText是相当不错,很好的实现,至少Delphi 2010版本我看看是相当有效(避免多个字符串分配,使用PChar“走”解析字符串)和工作方式与Excel的解析器相同。>在现实世界中,您需要与使用其他库(或根本没有库)编写的其他软件交换数据,其中人们可能会错过解释CSV的一些(缺少的)规则。你必须适应,它可能不是一个正确或错误的情况,但是一个“我的客户需要导入这个垃圾”的情况。如果发生这种情况,你必须编写自己的解析器,一个适应你要处理的第三方应用程序的要求。在这之前,你可以安全地使用TStrings。当它发生时,它可能不是TString的错!