从分隔符分隔值文件中恢复数据集

时间:2011-06-17 12:29:38

标签: delphi delphi-xe changelog

简而言之,我是delphi的新手,我希望实现以下目标:

  • 我将表定义为.cds文件{index,data,date}和.csv格式的一些数据。
  • 我想将.csv文件加载到表中并显示日志的更改和错误(例如:无效的日期格式)。

问题

如何优雅地解决这个问题?

4 个答案:

答案 0 :(得分:3)

您可以从.csv逐行读取,将每行设置为StringList的'DelimitedText',将记录追加到数据集,循环字符串列表以设置每个字段的值,然后发布到数据集。
您可以将'字段值分配'/'发布'放在try-except块中,并将引发异常的任何错误消息与您喜欢的信息一起记录(例如,格式错误的字段值/名称,行号和/或整行等)到文件fi

(我不明白你所说的“变化”是什么意思,根据我的理解,.csv中的行会插入到数据集中,因此所有更改都将被插入。)


编辑:能够就具体事情进行讨论(我很难掌握任务:))

示例数据(CodeGear示例'Clients.cds'的一部分):

  

戴维斯;珍; 1023495,0000; 100   酸果蔓   圣;韦尔斯利; MA; 02181; 516-292-3945; 93年1月1日   琼斯;亚瑟; 2094056,0000; 10 Hunnewell   圣;洛杉矶   图斯; CA; 94024; 415-941-4321; 81年7月2日   Parker; Debra; 1209395,0000; 74 South   圣;阿瑟顿; CA; 98765; 916-213-2234; 90年10月23日   Sawyer; Dave; 3094095,0000; 101奥克兰   圣;洛杉矶   图斯; CA; 94022; 415-948-9998; 89年12月21日   白色;辛迪; 1024034,0000; 1温特沃斯   博士,洛杉矶   托斯; CA; 94022; 415-948-6547; 92年1月10日

procedure TForm1.FormCreate(Sender: TObject);
begin
  CDS.FieldDefs.Add('LAST_NAME', ftString, 20);
  CDS.FieldDefs.Add('FIRST_NAME', ftString, 20);
  CDS.FieldDefs.Add('ACCT_NBR', ftInteger);
  CDS.FieldDefs.Add('ADDRESS_1', ftString, 30);
  CDS.FieldDefs.Add('CITY', ftString, 15);
  CDS.FieldDefs.Add('STATE', ftString, 2);
  CDS.FieldDefs.Add('ZIP', ftString, 5);
  CDS.FieldDefs.Add('TELEPHONE', ftString, 12);
  CDS.FieldDefs.Add('DATE_OPEN', ftDate);
  CDS.CreateDataSet;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  csv: TextFile;
  Rec: string;
  Fields: TStringList;
  LineNo: Integer;
  i: Integer;
begin
  Fields := TStringList.Create;
  try
    Fields.StrictDelimiter := True;
    Fields.Delimiter := ';';

    AssignFile(csv, ExtractFilePath(Application.ExeName) + 'clients.csv');
    try
      Reset(csv);

      LineNo := 0;
      while not Eof(csv) do begin
        Inc(LineNo);
        Readln(csv, Rec);

        Fields.DelimitedText := Rec;
        CDS.Append;

        for i := 0 to Fields.Count - 1 do
          try
            CDS.Fields[i].Value := Fields[i];   // Variant conversion will raise
                                 // exception where conversion from string fails
          except
            on E:EDatabaseError do begin
              CDS.Cancel;        // Failed, discard the record

              // log the error instead of showing a message
              ShowMessage(Format('Cannot set field "%s" at line %d' + sLineBreak +
                  'Error: %s', [CDS.Fields[i].FieldName, LineNo, E.Message]));
              Break;             // Continue with next record
            end;
          end;

        if CDS.State = dsInsert then // It's not dsInsert if we Cancelled the Insert
          try
            CDS.Post;
          except
            on E:EDatabaseError do begin
              // log error instead of showing
              ShowMessage(Format('Cannot post line %d' + sLineBreak + 'Error: %s',
                  [LineNo, E.Message]));
              CDS.Cancel;
            end;
          end;

      end;
    finally
      CloseFile(csv);
    end;
  finally
    Fields.Free;
  end;
end;

procedure TForm1.CDSBeforePost(DataSet: TDataSet);
begin
  // Superficial posting error
  if CDS.FieldByName('LAST_NAME').AsString = '' then
    raise EDatabaseError.Create('LAST_NAME cannot be empty');
end;

答案 1 :(得分:3)

我会使用JvCsvDataSet(JEDI JVCL组件),因为它正确解析CSV文件,然后使用数据泵组件,将数据移动到客户端数据集中,以及一些验证。

但是,如果您真正需要做的就是提供一个CSV文件,那么我将完全省略ClientDataSet,并且只使用为您尝试的目的而构建的组件。不要将螺钉用作钉子,也不要将钉子用作螺钉。它们都是金属制成的,但它们可以做不同的工作。

CSV文件表定义在目的上与CDS表定义完全不同,JvCsvDataSet提供了一个简单的字符串属性,您可以设置该属性以提供元数据(字段数据类型,如整数或字符串或日期时间,以及关联字段名称,对于缺少标题行的CSV文件,比您希望在ClientDatSet中更容易实现。

答案 2 :(得分:2)

AFAIK,没有直接的方法将.csv数据加载到TClientDataset

我能想到的最简单的方法是使用TTextDataSetDemos\Delphi\Database\TextData中找到的Start->All Programs->Embarcadero RAD Studio XE->Samples)。你可以像任何其他TDataSet一样使用它,这意味着你可以从它Fields读取或使用FieldByName,它支持BofEofNext,和Prior

您可以简单地遍历并尝试分配到CDS列,然后它会生成您可以处理或记录的错误。

您可以像任何其他组件一样安装TTextDataset,或者只是将单元添加到uses子句并在运行时创建它。文件夹中有一个readme.htm文件,说明不多;关键属性为FileNameActive。 :)

它包括预先设计的包(TextPkg.dproj)和测试应用(TextTest.dproj)。还有一个项目组(TextDataGroup.groupproj) - 你可以在IDE中打开它,构建并安装TextPkg包,然后编译并运行测试应用程序。测试应用程序的源代码显示效果非常好。

答案 3 :(得分:1)

如果数据库是DBISAM的可能性很小,您只需使用IMPORT SQL语句。

import table "tablename" from "myinputfile.csv" Delimiter ',';

其他数据库可能具有类似功能。