将大量字符串添加到 TStringList 时出现问题
我在将字符串添加到 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
加载列表,但我不想在应用程序之外有文本文件。
我希望你能帮助我!如果您需要任何进一步的信息,请告诉我。
非常感谢。我真的很感谢你的帮助。
I have a problem adding strings to a TStringList. I've searched other posts but couldn't find an answer to this.
What I'm trying to do is to add a big amount of strings to a TStringList (more than 14000) but somewhere in the process I get an EAccessViolation. Here's the code I'm using:
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;
¿What's wrong with this code? The list contains duplicate strings so I set the Duplicates
property to dupAccept
. I was able to load the list using LoadFromFile
, but I don't want to have a text file outside my application.
I hope you can help me!!! Please tell me if you need any further information.
Thank you very much. I really appreciate your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
使用外部文件的建议就在此处。但是,您的帖子表明您希望没有外部文件。然后我建议您将该文件作为资源链接到可执行文件。您可以按照以下步骤轻松执行此操作:
将所有字符串放入名为 stringdata.txt(或您选择的任何名称)的文本文件中。然后创建一个您选择的任何名称的 .rc 文件,并将以下内容放入其中(STRING_DATA 可以是您选择的任何标识符):
从 .rc 创建一个 .res 文件:
现在从源代码引用此文件。将以下内容放置在单元中的某个位置:
不要从文件流加载,而是从资源流加载:
如果您进行命令行自动构建,我建议您将 .rc 文件置于源代码控制下,并在运行期间构建 .res构建过程。通过这种方式,您还可以将 stringdata.txt 文件置于源代码管理之下,并且任何编辑都会在下一个构建中自动捕获,而无需在每次 .txt 文件更改时显式构建 .res 文件。
The suggestions for using an external file are on the mark here. However, your post indicates your desire for not having an external file. I would then suggest you link the file to the executable as a resource. You can easily do this following these steps:
Place all the strings into a text file called stringdata.txt (or whatever name you choose). Then create a .rc file of whatever name you choose and put the following into it (STRING_DATA can be any identifier you choose):
Create a .res file from the .rc:
Now reference this file from the source code. Place the following someplace in the unit:
Instead of loading from a file stream, load from a resource stream:
If you do command-line automated builds, I would suggest you keep the .rc file under source control and build the .res during the build process. This way you can also keep the stringdata.txt file under source control and any edits are automatically caught on the next build without having to explicitly build the .res file each time the .txt file changes.
您使用的 Delphi 版本是什么?某些旧版本的内存管理器存在错误,当尝试将数组重新分配到太大的大小时,可能会导致访问冲突。
尝试将 FastMM4 添加到您的项目中以替换旧的内存管理器,看看是否有帮助。
另外,您最好将列表保存在外部文件中。是的,它是另一个文件,但这也意味着您可以更改列表,而无需重新编译整个程序。这也使得创建(和分发!)更新变得更加容易。
What Delphi version are you using? Some older versions had a bug in the memory manager that can cause an access violation when trying to reallocate an array to a size that's too large.
Try adding FastMM4 to your project to replace the old memory manager and see if that helps.
Also, you're probably better off keeping the list in an external file. Yes, it's another file, but it also means that you can change the list without having to recompile the entire program. This also makes creating (and distributing!) updates easier.
梅森对于 AV 的主张可能是正确的;这是一个相当大的数组,需要增长。
顺便说一句,当对 StringList 进行如此长的处理时,建议用 BeginUpdate/EndUpdate 包围它,以避免触发任何更新事件。
即使您现在没有,以后可能会添加它们,您会遇到问题。
Mason is probably right for the cause of the AV; this is quite a large array to grow.
On a side note, when doing such a long processing on a StringList, it's recommended to surround it by BeginUpdate/EndUpdate to avoid firing any update event.
Even if you don't have any now, they might be added later and you'll get problems.
创建列表后立即将 list.capacity 设置为您计划添加的项目数。或者,将列表放入 RC 文件中(以项目名称以外的名称命名)并将其添加到您的项目中。这将被编译到您的应用程序中,但不涉及创建列表的可执行代码。
Set list.capacity to the number of items you plan to add, immediately after you create the list. Alternatively, place the list in an RC file (named other than with the name of your project) and add it to your project. This gets compiled into your application, but does not involve executable code to create the list.
我还会担心 14,000 行程序的编译器完整性。人们还发现了其他情况,超出任何合理范围会以各种方式破坏编译器。
I would also worry about compiler integrity with a 14,000 line procedure. People have found other cases where going beyond anything reasonable breaks the compiler in various ways.
您可能还想尝试 THashedStringList,可以看到速度提升(尽管不在这个函数中),尽管我不确定 add 方法是否有很大不同。
You may also want to try THashedStringList, could see a speed boost (although not in this function), although I'm not sure if the add method is a whole lot different.
尝试使用以下代码而不是您的代码将字符串添加到 StringList
var
str:字符串;
开始
Str := '125-AMPLE' + #13#10;
Str := Str + 'TCUMSON' + #13#10;
Str := Str + 'ATLV 4300' + #13#10;
字符串 := 字符串 + '150T-15' + #13#10;
........
列表.Text := Str;
结尾;
try using the following instead of your code to add the strings to the StringList
var
Str: string;
begin
Str := '125-AMPLE' + #13#10;
Str := Str + 'TCUMSON' + #13#10;
Str := Str + 'ATLV 4300' + #13#10;
Str := Str + '150T-15' + #13#10;
................
List.Text := Str;
end;