You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 11.2如何拆分CSV字符串时忽略双引号内的逗号?

解决Delphi 11.2中CSV解析错误拆分引号内逗号的问题

我用Delphi 11.2开发,已经通过以下代码初始化了TStringList准备处理CSV:

procedure TForm2.FormCreate(Sender: TObject);
begin
  SL := TStringList.Create;
  SL.Delimiter := ',';        // 默认分隔符,部分地区会用";"
  SL.QuoteChar := '"';        // 默认引号字符
  SL.StrictDelimiter := True; // 严格仅按Delimiter分隔字符串
end; 

CSV示例数据:

20211605344,04/23/2021 - 09:26:42 am,4/28/2021,"Wood Drive, ENFIELD, CT","Calini, CBM",3223837, ENFIELD,Hartford,1,3,No as-built attached

20211300637,03/29/2021 - 11:48:51 am,4/1/2021,"Enfield Street, ENFIELD, CT",CBM,3223846, ENFIELD,Hartford,2,0,Job changed to aerial

尝试用以下代码将每行拆分为动态数组分配字段时,出现了错误:

procedure TForm2.Button2Click(Sender: TObject);
var
  i:integer;
  TicketNumber:string;
  oneStr: TStringDynArray;
  val:double;
begin
  SL.LoadFromFile('D:\DelphiProjects\ImportCSV\PURA Phase 2 inspection selection.csv');
  for I := 1 to SL.Count-1 do
    begin
      oneStr:= SplitString(SL[i], ',');
      TicketNumber:= oneStr[0];
      If TryStrToFloat(TicketNumber, val)then
        memo2.Lines.Add('TicketNo: '+oneStr[0]+' '+'Job Date: '+oneStr[1]+' '+ 'Job Start: '+oneStr[2]+' '+'Address: '+oneStr[3]+' '+ 'Crew: '+oneStr[4]+' '+'Project: '+oneStr[5]+' '+'Town: '+oneStr[6]+' '+'County: '+oneStr[7]+' '+'Order: '+oneStr[8]+' '+'Count: '+oneStr[9]+' '+'Note: '+oneStr[10]);
    end;   
end;

运行后错误拆分了双引号内的逗号,导致字段错位,输出结果:

TicketNo: 20211605344 Job Date: 04/23/2021 - 09:26:42 am Job Start: 4/28/2021 Address: "Wood Drive Crew:  ENFIELD Project:  CT" Town: "Calini County:  CBM" Order: 3223837 Count:  ENFIELD Note: Hartford
TicketNo: 20211300637 Job Date: 03/29/2021 - 11:48:51 am Job Start: 4/1/2021 Address: "Enfield Street Crew:  ENFIELD Project:  CT" Town: CBM County: 3223846 Order:  ENFIELD Count: Hartford Note: 2

问题原因

SplitString是简单的字符串拆分函数,只会按指定的分隔符拆分,完全忽略CSV格式中双引号内的逗号不作为分隔符的规则,因此导致字段错位。

正确解决方案

你已经初始化的TStringList已经配置了CSV解析所需的Delimiter、QuoteChar和StrictDelimiter属性,直接利用它的DelimitedText属性来解析每行即可,无需使用SplitString。

修改后的代码如下:

procedure TForm2.Button2Click(Sender: TObject);
var
  i: Integer;
  TicketNumber: string;
  val: Double;
  LineParser: TStringList;
begin
  SL.LoadFromFile('D:\DelphiProjects\ImportCSV\PURA Phase 2 inspection selection.csv');
  // 创建临时的TStringList用于解析每行
  LineParser := TStringList.Create;
  try
    LineParser.Delimiter := ',';
    LineParser.QuoteChar := '"';
    LineParser.StrictDelimiter := True;
    LineParser.QuoteStrings := False; // 可选:解析后自动去掉字段的引号

    for I := 0 to SL.Count - 1 do
    begin
      // 跳过空行
      if Trim(SL[i]) = '' then Continue;
      
      LineParser.DelimitedText := SL[i];
      TicketNumber := LineParser[0];
      if TryStrToFloat(TicketNumber, val) then
      begin
        memo2.Lines.Add(Format('TicketNo: %s Job Date: %s Job Start: %s Address: %s Crew: %s Project: %s Town: %s County: %s Order: %s Count: %s Note: %s',
          [LineParser[0], LineParser[1], LineParser[2], LineParser[3], LineParser[4],
           LineParser[5], LineParser[6], LineParser[7], LineParser[8], LineParser[9], LineParser[10]]));
      end;
    end;
  finally
    LineParser.Free;
  end;
end;

关键改动说明

  1. 创建临时TStringList作为行解析器,复用CSV的格式配置;
  2. 使用DelimitedText属性赋值当前行,它会自动识别双引号包裹的字段,忽略内部的逗号;
  3. 新增QuoteStrings := False(可选),解析后自动移除字段前后的双引号,让输出更整洁;
  4. 增加空行判断,避免处理空行导致索引越界;
  5. 使用Format函数拼接字符串,代码更易读。

正确输出结果

运行修改后的代码,会得到正确的字段拆分结果:

TicketNo: 20211605344 Job Date: 04/23/2021 - 09:26:42 am Job Start: 4/28/2021 Address: Wood Drive, ENFIELD, CT Crew: Calini, CBM Project: 3223837 Town:  ENFIELD County: Hartford Order: 1 Count: 3 Note: No as-built attached
TicketNo: 20211300637 Job Date: 03/29/2021 - 11:48:51 am Job Start: 4/1/2021 Address: Enfield Street, ENFIELD, CT Crew: CBM Project: 3223846 Town:  ENFIELD County: Hartford Order: 2 Count: 0 Note: Job changed to aerial

内容的提问来源于stack exchange,提问作者Meta Mussel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:05:38