问题缘起:
收到的 CSV 文件,有不同的格式。比如这种:
"a bird", "x profile", "this is a test"
另外,有这种:
a bird, x profile, this is a test
如何用 Delphi 代码分拆出 3 个字段来?
解决方法
对于第一种带双引号的,采用 TStringList,大概代码如下:
SL := TStringList.Create;
try
//将 csv 文件第一行取出来,当作表头,解析出字段.
SL.LoadFromFile(Fn);
S := SL[0];
SL.Clear;
SL.Delimiter := ',';
SL.DelimitedText := S;
//通用的表,因此,字段全部为字符串,长度为 100;
for I := 0 to SL.Count - 1 do
begin
Memo1.Lines.Add(SL[i]);
end;
finally
SL.Free;
end;
解释:设置 TStringList 的 Delmiter 是告诉它按照逗号分割字符串;设置 DelimitedText 是告诉它需要分割的字符串内容。结果它真的分割好了。有意思的是,分割好的字符串里面,不单单是去掉了作为分割符的逗号,连前后的双引号都没有了。
对于第二种没有带双引号的,上述方法不灵了。
第二种没有双引号的,采用上述方法,它不单根据双引号做了分割,还根据空格做了分割。因此,把原本应该是一个字段的几个单词,分割成了多个。
对于第二种没有双引号的,该怎么办?看代码:
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
SL: TStringList;
S: string;
A: TArray<string>;
begin
if OpenDialog1.Execute then
begin
SL := TStringList.Create;
try
SL.LoadFromFile(OpenDialog1.FileName);
S := SL[0];
{
SL.Delimiter := Char(','); //问题:采用 , 作为分隔,解决不了字符串中间的空格问题。它会把空格也当作分隔符,碰到空格也换行。
SL.DelimitedText := S; //这个是 TStringList 的问题。
Memo1.Lines.Clear;
for I := 0 to SL.Count - 1 do
begin
Memo1.Lines.Add(i.ToString + ' - ' + SL[i]);
end;
}
//使用以下方法可以做到
A := S.Split([',']);
for I := 0 to Length(A) -1 do
begin
Memo1.Lines.Add(i.ToString + ' - ' + A[i]);
end;
finally
SL.Free;
end;
end;
end;
解释一下:这里是采用了字符串的 Helper 函数 Split 这个函数。这里的代码告诉这个函数分割符是逗号,它就按逗号分割,将分割出来的多个字符串放入到一个字符串 Array 里面,这里的类型是 TArray<string>,这是一个泛型的类型定义。
测试结果表明,它确实按照逗号分割了。没有把空格也分割。
但是,如果用这个方法处理带双引号的,则它分割出来的字符串还带着双引号。因此如果它有双引号,还得自己再处理一下双引号。如果不想自己处理双引号,那就用第一种方法。