2

我在将字符串添加到 TStringList 时遇到问题。我搜索了其他帖子,但找不到答案。

我想要做的是向 TStringList(超过 14000 个)添加大量字符串,但在此过程中的某个地方我得到了 EAccessViolation。这是我正在使用的代码:

procedure TForm1.FormCreate(Sender: TObject);
begin
    List := TStringList.Create;
    List.Duplicates := dupAccept;
end;

procedure TForm1.ButtonStartClick(Sender: TObject);
begin
    List.Clear;
    List.Add('125-AMPLE');
    List.Add('TCUMSON');
    List.Add('ATLV 4300');
    List.Add('150T-15');
    List.Add('TDL-08ZE');
    List.Add('RT20L');
    List.Add('SIN LINEA');
    List.Add('TIARA');
    List.Add('FL200ZK1');
    List.Add('FL250ZK1');
    List.Add('SIN LINEA');
    List.Add('CENTAURO-70 S.P.');
    List.Add('CORSADO');

{ This list continues to about 14000 strings...}

    List.Add('VOSJOD 2');
    List.Add('Z 125');
    List.Add('ZUMY');
    List.Add('NEW AGE 125');
    List.Add('SIN LINEA');
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    FreeAndNil(List);
end;

¿ 这段代码有什么问题?该列表包含重复的字符串,因此我将Duplicates属性设置为dupAccept. 我能够使用 加载列表LoadFromFile,但我不想在我的应用程序之外有一个文本文件。

我希望你能帮帮我!!!如果您需要任何进一步的信息,请告诉我。

非常感谢你。我真的很感谢你的帮助。

4

7 回答 7

18

使用外部文件的建议在此处标记。但是,您的帖子表明您希望没有外部文件。然后,我建议您将文件作为资源链接到可执行文件。您可以按照以下步骤轻松执行此操作:

将所有字符串放入名为 stringdata.txt(或您选择的任何名称)的文本文件中。然后创建一个您选择的任何名称的 .rc 文件并将以下内容放入其中(STRING_DATA 可以是您选择的任何标识符):

STRING_DATA RCDATA "stringdata.txt"

从 .rc 创建一个 .res 文件:

BRCC32 <name of rc>.rc

现在从源代码中引用这个文件。将以下内容放置在单元中的某个位置:

{$R <name of res>.res}

不是从文件流加载,而是从资源流加载:

StringData := TResourceStream.Create(HInstance, 'STRING_DATA', RT_RCDATA);
try
  List.LoadFromStream(StringData);
finally
  StringData.Free;
end;

如果您进行命令行自动构建,我建议您将 .rc 文件置于源代码管理之下,并在构建过程中构建 .res。这样,您还可以将 stringdata.txt 文件置于源代码控制之下,并且在下一次构建时会自动捕获任何编辑,而无需在每次 .txt 文件更改时显式构建 .res 文件。

于 2009-12-14T23:22:52.217 回答
3

你用的是什么德尔福版本?一些旧版本的内存管理器中有一个错误,当尝试将数组重新分配为太大的大小时,可能会导致访问冲突。

尝试将FastMM4添加到您的项目中以替换旧的内存管理器,看看是否有帮助。

此外,您最好将列表保存在外部文件中。是的,它是另一个文件,但这也意味着您可以更改列表而无需重新编译整个程序。这也使得创建(和分发!)更新更容易。

于 2009-12-14T21:55:14.377 回答
2

梅森可能是正确的 AV 的原因;这是一个相当大的增长阵列。
附带说明一下,在对 StringList 进行如此长的处理时,建议用 BeginUpdate/EndUpdate 将其包围以避免触发任何更新事件。
即使您现在没有,也可能稍后添加它们,您会遇到问题。

于 2009-12-14T22:09:00.463 回答
1

在创建列表后立即将 list.capacity 设置为您计划添加的项目数。或者,将列表放在一个 RC 文件中(命名与您的项目名称不同)并将其添加到您的项目中。这会编译到您的应用程序中,但不涉及创建列表的可执行代码。

于 2009-12-14T23:05:09.367 回答
1

我还会担心 14,000 行过程的编译器完整性。人们发现了其他情况,超出任何合理范围会以各种方式破坏编译器。

于 2009-12-15T01:23:23.003 回答
0

您可能还想尝试 THashedStringList,可以看到速度提升(尽管不在此函数中),尽管我不确定 add 方法是否有很大不同。

于 2009-12-14T23:05:55.240 回答
-4

尝试使用以下代码而不是您的代码将字符串添加到 StringList

var
Str: 字符串;
开始
Str := '125-AMPLE' + #13#10;
力量 := 力量 + 'TCUMSON' + #13#10;
力量 := 力量 + 'ATLV 4300' + #13#10;
力量 := 力量 + '150T-15' + #13#10;
......

List.Text := 字符串;

结尾;

于 2009-12-15T05:15:57.913 回答