gpt4 book ai didi

delphi - TStringList 拆分错误

转载 作者:行者123 更新时间:2023-12-03 14:33:06 26 4
gpt4 key购买 nike

最近,一位信誉良好的 SO 用户通知我,TStringList 存在拆分错误,这会导致它无法解析 CSV 数据。我还没有被告知这些错误的性质,并且在互联网上进行了搜索,包括 Quality Central没有产生任何结果,所以我才问。什么是TStringList 拆分错误

注意,我对毫无根据的意见答案不感兴趣。


我所知道的:

不多......其中之一是,这些错误很少在测试数据中出现,但在现实世界中并不罕见。

另一个是,如上所述,它们会阻止正确解析 CSV。考虑到很难用测试数据重现这些错误,我(可能)正在向尝试过在生产代码中使用字符串列表作为 CSV 解析器的人寻求帮助。

不相关的问题:

我获得了有关“Delphi-XE”标记问题的信息,因此由于“空格字符被视为分隔符”而导致解析失败feature请勿应用。因为StrictDelimiter的介绍Delphi 2006 的属性解决了这个问题。我本人正在使用 Delphi 2007。

另外由于字符串列表只能容纳字符串,因此它只负责分割字段。由于区域设置差异等引起的涉及字段值(例如日期、 float ......)的任何转换困难不在范围内。

基本规则:

CSV 没有标准规范。但从 various specifications 推断出一些基本规则。

下面演示了 TStringList 如何处理这些。规则和示例字符串来自Wikipedia 。括号 ([ ]) 叠加在字符串周围,以便能够通过测试代码看到前导或尾随空格(如果相关)。


空格被视为字段的一部分,不应被忽略。

Test string: [1997, Ford , E350]Items: [1997] [ Ford ] [ E350]


Fields with embedded commas must be enclosed within double-quote characters.

Test string: [1997,Ford,E350,"Super, luxurious truck"]Items: [1997] [Ford] [E350] [Super, luxurious truck]


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 string: [1997,Ford,E350,"Super, ""luxurious"" truck"]Items: [1997] [Ford] [E350] [Super, "luxurious" truck]


Fields with embedded line breaks must be enclosed within double-quote characters.

Test string: [1997,Ford,E350,"Go get one nowthey are going fast"]Items: [1997] [Ford] [E350] [Go get one nowthey are going fast]


In CSV implementations that trim leading or trailing spaces, fields with such spaces must be enclosed within double-quote characters.

Test string: [1997,Ford,E350," Super luxurious truck "]Items: [1997] [Ford] [E350] [ Super luxurious truck ]


Fields may always be enclosed within double-quote characters, whether necessary or not.

Test string: ["1997","Ford","E350"]Items: [1997] [Ford] [E350]



Testing code:

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, Ford , E350');

rule := 'Fields with embedded commas must be enclosed within double-quote characters.';
Test('1997,Ford,E350,"Super, 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,Ford,E350,"Super, ""luxurious"" truck"');

rule := 'Fields with embedded line breaks must be enclosed within double-quote characters.';
Test('1997,Ford,E350,"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,Ford,E350," Super luxurious truck "');

rule := 'Fields may always be enclosed within double-quote characters, whether necessary or not.';
Test('"1997","Ford","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.

只需要一个案例。测试数据不是随机数据,一个有一个失败案例的用户应该提交数据,然后我们就得到了一个测试案例。如果没有人可以提供测试数据,也许就没有错误/失败?

There's no standard specification for CSV.

这确实有助于消除困惑。如果没有标准规范,如何证明某些事情是错误的?如果仅靠自己的直觉,你可能会遇到各种各样的麻烦。以下是我自己与政府发行的软件愉快互动的一些内容;我的应用程序应该以 CSV 格式导出数据,而政府应用程序应该导入它。以下是我们连续几年陷入很多麻烦的原因:

  • 如何表示空数据?由于没有 CSV 标准,有一年,我友好的政府决定一切都可以,包括什么都不做(两个连续的逗号)。接下来他们决定只有连续的逗号才可以,即Field,"",Field无效,应该是Field,,Field。我很有趣地向我的客户解释政府应用程序从一周到下一周更改了验证规则......
  • 是否导出零整数数据?这可能是一个更大的滥用,但我的“政府应用程序”决定也验证这一点。曾经强制包含 0,然后又强制不包含 0。也就是说,在某个时间 Field,0,Field 有效,下一个 Field,,Field 是唯一有效的方式...

这是另一个测试用例,(我的)直觉失败了:

1997, Ford, E350, "Super, luxurious truck"

请注意,"Super之间的空格,以及"Super后面的非常幸运的逗号。 TStrings 使用的解析器仅在紧跟在分隔符之后的情况下才能看到引号字符。该字符串被解析为:

[1997]
[ Ford]
[ E350]
[ "Super]
[ luxurious truck"]

直觉上我期望:

[1997]
[ Ford]
[ E350]
[Super luxurious truck]

但是你猜怎么着,Excel 的做法与 Delphi 的做法相同...

结论

  • TStrings.CommaText 相当好并且实现得很好,至少我看过的 Delphi 2010 版本相当有效(避免了多个字符串分配,使用 PChar 来“walk”已解析的字符串),其工作方式与 Excel 的解析器大致相同。
  • 在现实世界中,您需要与使用其他库(或根本没有库)编写的其他软件交换数据,人们可能会错误地解释 CSV 的一些(缺失?)规则。你必须适应,这可能不是一个对错的问题,而是一个“我的客户需要导入这些垃圾”的情况。如果发生这种情况,您将不得不编写自己的解析器,该解析器可以适应您要处理的第 3 方应用程序的要求。在此之前,您可以安全地使用 TStrings。当它确实发生时,可能不是 TString 的错!

关于delphi - TStringList 拆分错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6461140/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com