最近,我收到了一位知名 SO 用户的通知,该用户TStringList
存在拆分错误,这将导致它无法解析 CSV 数据。我没有被告知这些错误的性质,包括Quality Central在内的互联网搜索没有产生任何结果,所以我在问。什么是TStringList 拆分错误?
请注意,我对基于毫无根据的意见的答案不感兴趣。
我知道的:
不多......一个是,这些错误很少出现在测试数据中,但在现实世界中并不罕见。
另一个是,如前所述,它们阻止正确解析 CSV。考虑到很难用测试数据重现错误,我(可能)正在向那些尝试在生产代码中使用字符串列表作为 CSV 解析器的人寻求帮助。
无关问题:
我获得了有关“Delphi-XE”标记问题的信息,因此由于“空格字符被视为分隔符” 功能而导致解析失败不适用。因为 Delphi 2006 引入的StrictDelimiter
属性解决了这个问题。我自己正在使用 Delphi 2007。
另外由于字符串列表只能保存字符串,所以它只负责拆分字段。任何涉及由区域设置差异等引起的字段值(fi 日期,浮点数......)的转换困难都不在范围内。
基本规则:
CSV 没有标准规范。但是从各种规范中可以推断出一些基本的规律。
下面是 TStringList 如何处理这些的演示。规则和示例字符串来自Wikipedia。括号 ( [
]
) 叠加在字符串周围,以便能够通过测试代码查看前导或尾随空格(如果相关)。
空格被认为是字段的一部分,不应被忽略。
测试字符串:[1997, Ford , E350] 项目:[1997] [福特] [E350]
带有嵌入逗号的字段必须用双引号括起来。
测试字符串:[1997,Ford,E350,"Super, Luxury truck"] 项目:[1997] [福特] [E350] [超级,豪华卡车]
嵌入双引号字符的字段必须包含在双引号字符内,并且每个嵌入的双引号字符必须由一对双引号字符表示。
测试字符串:[1997,Ford,E350,"Super, ""luxurious""卡车"] 项目:[1997] [福特] [E350] [超级,“豪华”卡车]
带有嵌入换行符的字段必须用双引号括起来。
测试字符串:[1997,Ford,E350,"现在去买一个 他们走得很快”] 项目:[1997] [福特] [E350] [现在去买一个 他们走得很快]
在修剪前导或尾随空格的 CSV 实现中,具有此类空格的字段必须用双引号字符括起来。
测试字符串:[1997,福特,E350,“超豪华卡车”] 项目:[1997] [福特] [E350] [超豪华卡车]
字段可能总是包含在双引号字符中,无论是否必要。
测试字符串:["1997","Ford","E350"] 项目:[1997] [福特] [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, 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 拆分错误”?