Das hättest du aber einfacher haben können. Deine Implementierung ist weitestgehend identisch mit TStringList, lediglich das LoadFromFile und SaveToFile gehen etwas sparsamer mit dem Speicher um. In der bordeigenen StringList wird die Datei zunächst in einen lokalen Buffer gelesen und dann erst in die StringList übertragen. Das kann bei einer sehr großen Datei in 32-Bit schon mal zu einem Out-Of-Memory führen. Die folgende Implementierung geht da etwas sparsamer mit dem Speicher um.
Es bleibt aber immer noch das Problem, daß alle Zeilen überhaupt in den Speicher passen müssen. Bedenkt man, daß intern mit 2 Byte pro Zeichen zu rechnen ist, die Datei aber womöglich in
ANSI oder UTF-8 codiert ist, kann das schon bei einer ca. 1 GB großen Datei zum Problem werden. Bei 30 Millionen Zeilen bleiben da pro Zeile auch nur ca. 30 Zeichen. Ab da sollte man spätestens über eine virtuelle TStrings-Implementation nachdenken.
Delphi-Quellcode:
type
TMemorySparingStringList = class(TStringList)
public
procedure LoadFromStream(Stream: TStream; Encoding: TEncoding); override;
procedure SaveToStream(Stream: TStream; Encoding: TEncoding); override;
procedure AppendToFile(const DateiName: String);
end;
procedure TMemorySparingStringList.AppendToFile(const DateiName: String);
var
writer: TStreamWriter;
I: Integer;
begin
writer := TStreamWriter.Create(DateiName, true);
try
for I := 0 to Count - 1 do begin
writer.WriteLine(Strings[I]);
end;
finally
writer.Free;
end;
end;
procedure TMemorySparingStringList.LoadFromStream(Stream: TStream; Encoding: TEncoding);
var
reader: TStreamReader;
begin
BeginUpdate;
try
reader := TStreamReader.Create(Stream, Encoding);
try
while not reader.EndOfStream do begin
Add(reader.ReadLine);
end;
finally
reader.Free;
end;
finally
EndUpdate;
end;
end;
procedure TMemorySparingStringList.SaveToStream(Stream: TStream; Encoding: TEncoding);
var
writer: TStreamWriter;
I: Integer;
begin
writer := TStreamWriter.Create(Stream, Encoding);
try
for I := 0 to Count - 1 do begin
writer.WriteLine(Strings[I]);
end;
finally
writer.Free;
end;
end;