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