gpt4 book ai didi

csv - Delphi 将多个 CSV 文件导入数据集时减速

转载 作者:行者123 更新时间:2023-12-03 18:34:52 25 4
gpt4 key购买 nike

我正在使用 Delphi 7、Windows 7 和绝对数据库。

快速背景。我在一家慈善商店工作,该商店依赖捐赠给我们的元素。要从我们的 HMRC 收回“礼品援助”,我们必须提交所有销售的详细信息以及该销售的每个捐赠者的姓名和地址。我们帮助有特殊需要的人,因此准确的数据输入很重要。

到目前为止检查邮政编码验证很容易(基于我们本地)基本上是AA00_0AA的格式或 AA0_0AA .由于我们的名字已经广为人知,并非所有邮政编码都遵循这些规则。

我可以访问英国皇家邮政数据库以获取英国地址,我想将输入的邮政编码与真实的邮政编码进行实际比较。 RM csv 文件很大,所以我使用 GSplit3 将其分解为更易于管理的文件。这给我留下了 492 个 csv 文件,每个文件由大约 62000 行组成。请注意,我只对邮政编码感兴趣,因此存在大量重复。

要将这些文件加载​​到数据集中(不重复),我首先将文件名加载到列表框中并运行循环以遍历所有文件以复制到数据服务器。为了避免重复,我尝试在字段上放置唯一索引,但即使在 Delphi 之外运行时,我仍然收到有关重复的错误消息。然后我 try catch 要附加的最后一条记录的文本,然后将其与下一条记录进行比较

   procedure TForm1.importClick(Sender: TObject);
var
i,y:Integer;
lstfile:string;
begin
for i:= 0 to ListBox1.Items.Count-1 do
begin
lstfile:='';
cd.Active:=False;//cd is a csv dataset loaded with csv file
cd.FileName:='C:\paf 112018\CSV PAF\'+ListBox1.Items[i];
cd.Active:=True;
while not cd.Eof do
begin
if (lstfile:=cd.Fields[0].AsString=cd.Fields[0].AsString) then cd.Next
else
table1.append;
table1.fields[0].asstring:=cd.Fields[0].AsString;
lstfile:=cd.Fields[0].AsString;
cd.Next;
end;
end;
table1.Edit;
table1.Post;
end;

尽管数据集中的记录总数似乎很低,但这似乎工作正常。我检查了我自己的邮政编码,虽然找到了另一个邮政编码,但它并不存在。很明显,记录已被跳过。然后我尝试使用 dupignore 将 CSV 文件加载到字符串列表中,然后将字符串列表复制到数据集。
        unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, DBGrids, SMDBGrid, StdCtrls, DB, ABSMain, SdfData;

type
TForm1 = class(TForm)
cd: TSdfDataSet;
dscd: TDataSource;
dst: TDataSource;
ABSDatabase1: TABSDatabase;
table1: TABSTable;
table1PostCode: TStringField;
Label2: TLabel;
ListBox1: TListBox;
getfiles: TButton;
import: TButton;
procedure getfilesClick(Sender: TObject);
procedure importClick(Sender: TObject);

private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
num:Integer;
implementation

{$R *.dfm}
procedure ListFileDir(Path: string; FileList: TStrings);
var
SR: TSearchRec;
begin
if FindFirst(Path + '*.csv', faAnyFile, SR) = 0 then
begin
repeat
if (SR.Attr <> faDirectory) then
begin
FileList.Add(SR.Name);
end;
until FindNext(SR) <> 0;
FindClose(SR);
end;
end;

procedure TForm1.getfilesClick(Sender: TObject);
begin//Fill listbox with csv files
ListFileDir('C:\paf 112018\CSV PAF\', ListBox1.Items);
end;

//start to iterate through files to appane to dataset
procedure TForm1.importClick(Sender: TObject);
var
i,y:Integer;
myl:TStringList;
begin

for i:= 0 to ListBox1.Items.Count-1 do
begin
myl:=TStringList.Create;
myl.Sorted:=True;
myl.Duplicates:=dupIgnore;
cd.Active:=False;
cd.FileName:='C:\paf 112018\CSV PAF\'+ListBox1.Items[i];
cd.Active:=True;
while not cd.Eof do
begin
if (cd.Fields[0].AsString='')then cd.Next
else
myl.Add(cd.Fields[0].AsString);
cd.Next;
end;
for y:= 0 to myl.Count-1 do
begin
table1.Append;
table1.Fields[0].AsString:=myl.Strings[y];
end;
myl.Destroy;
end;
t.Edit;
t.Post;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
t.Locate('Post Code',edit1.text,[]);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
sel:string;
begin
q.Close;
q.SQL.Clear;
q.SQL.Add('Select * from postc where [Post Code] like :sel');
q.ParamByName('sel').AsString:=Edit1.Text;
q.Active:=True;
end;

end.

这开始很好,但很快就开始变慢,我想是因为内存泄漏,我尝试了 myl.free()、freeandnil(myl) 并最终销毁,但它们都很快变慢了。我不是专家,但我很喜欢使用 Delphi,通常会设法通过您的页面或谷歌搜索来解决问题,但这次我被难住了。有人可以建议一个更好的方法吗

最佳答案

下面显示了如何从包含邮政编码列表的文件中添加邮政编码
到查询类型的数据集,例如 TAdoQuery 或您的 q数据集(你的 q 没有说什么类型
据我所知,它是)。

从你所说的看来,虽然你对待你的邮政编码文件
作为 CVS 文件,您实际上不需要:如果记录仅包含一个
字段,应该不需要逗号,因为没有什么可以分隔的,
该文件应每行仅包含一个邮政编码。因此,有
似乎不需要将其加载为 CSV 文件的开销,因此您应该能够简单地将其加载到 TStringList 并从那里添加邮政编码。

我不会尝试更正您的代码,只是展示一个非常简单的示例来说明我认为应该如何完成。
所以下面的代码打开一个邮政编码列表文件,假设每行包含一个邮政编码,检查其中的每个条目是否
已经存在于您的邮政编码表中,如果不存在则添加它。

  procedure TForm1.AddPostCodes(const PostCodeFileName: String);
// The following shows how to add postcodes to a table of existing ones
// from a file named PostCodeFileName which should include an explicit path
var
PostCodeList : TStringList;
PostCode : String;
i : Integer;
begin
PostCodeList := TStringList.Create;
try
PostCodeList.LoadFromFile(PostCodeFileName);
if qPostCodes.Active then
qPostCodes.Close;
qPostCodes.Sql.Text := 'select * from postcodes order by postcode';

qPostCodes.Open;
try
qPostCodes.DisableControls; // Always call DisableControls + EnableControls
// when iterating a dataset which has db-aware controls connected to it
for i := 0 to PostCodeList.Count - 1 do begin
PostCode := PostCodeList[i]; // use of PostCode local variable is to assist debuggging
if not qPostCodes.Locate('PostCode', PostCode, [loCaseInsensitive]) then
qPostCodes.InsertRecord([PostCode]); // InsertRecord does not need to be foollowed by a call to Post.
end;
finally
qPostCodes.EnableControls;
qPostCodes.Close;
end;
finally
PostCodeList.Free; // Don't use .Destroy!
end;
end;

顺便说一句,关于将数据集的迭代括起来的评论
通过调用 DisableControls 和 EnableControls,这样做的通常原因是避免更新 gui 显示连接到数据集的任何 db-aware 控件的开销。然而,我的原因之一
不愿意推测是什么导致你的速度变慢是 TAdoQuery,
它是使用 Delphi 编码的标准数据集类型之一,受益匪浅
来自 DisableControls/EnableControls,即使没有 db-aware 控件
连接到它。这是因为 TAdoQuery 编码中的一个怪癖。任何
您正在使用的数据集可能有类似的怪癖。

关于csv - Delphi 将多个 CSV 文件导入数据集时减速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55195488/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com