2

TStringList に文字列を追加する際に問題があります。他の投稿を検索しましたが、これに対する答えが見つかりませんでした。

私がやろうとしているのは、大量の文字列 (14000 以上) を TStringList に追加することですが、プロセスのどこかで 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

使用している Delphi のバージョンは何ですか? 一部の古いバージョンでは、メモリ マネージャーにバグがあり、配列を大きすぎるサイズに再割り当てしようとすると、アクセス違反が発生する可能性がありました。

プロジェクトにFastMM4を追加して、古いメモリ マネージャーを置き換えてみて、それが役立つかどうかを確認してください。

また、リストを外部ファイルに保存した方がよいでしょう。はい、これは別のファイルですが、プログラム全体を再コンパイルすることなくリストを変更できることも意味します。これにより、更新の作成 (および配布!) も容易になります。

于 2009-12-14T21:55:14.377 に答える
2

メイソンはおそらくAVの原因として正しいでしょう。これは非常に大きな配列です。
ちなみに、StringList でこのような長い処理を行う場合は、更新イベントの発生を避けるために、BeginUpdate/EndUpdate で囲むことをお勧めします。
現在何も持っていなくても、後で追加される可能性があり、問題が発生する可能性があります。

于 2009-12-14T22:09:00.463 に答える
1

また、14,000 行のプロシージャーでは、コンパイラーの整合性についても心配します。合理的な範囲を超えると、さまざまな方法でコンパイラが壊れる他のケースが見つかりました。

于 2009-12-15T01:23:23.003 に答える
1

リストを作成した直後に、list.capacity を追加する予定のアイテムの数に設定します。または、リストを RC ファイル (プロジェクト名以外の名前) に配置し、それをプロジェクトに追加します。これはアプリケーションにコンパイルされますが、リストを作成するための実行可能コードは必要ありません。

于 2009-12-14T23:05:09.367 に答える
0

THashedStringList を試してみることもできますが、add メソッドがまったく異なるかどうかはわかりませんが、(この関数ではありませんが) 速度が向上する可能性があります。

于 2009-12-14T23:05:55.240 に答える
-4

コードの代わりに次を使用して、文字列を StringList に追加してみてください

var
Str: 文字列; 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;

終わり;

于 2009-12-15T05:15:57.913 に答える