delphi – TStringList分裂错误

最近我被一个有信誉的SO用户通知,TStringList有分裂错误,这将导致它无法解析CSV数据。我没有被告知这些错误的性质,在互联网上包括 Quality Central搜索没有产生任何结果,所以我问。什么是TStringList分解错误

请注意,我对基于意见的答案不感兴趣。

我知道的:

没有多少…一个是,这些错误很少显示测试数据,但在现实世界中不那么少。

一个是,如所述,它们阻止正确解析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的错!

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...