Я использую Embarcadero Rad Studio Delphi (10.2.3) и столкнулся с проблемой памяти при чтении в очень больших текстовых файлах (7 миллионов строк +, каждая строка отличается, строки могут иметь длину от 1 до 200 символов и т. Д..).Я довольно новичок в программировании на Delphi, поэтому я искал SO и Google в поисках помощи перед публикацией.
Первоначально я реализовал TStringList и прочитал файл с помощью метода LoadFromFile, но это не получилось, когда обработанные текстовые файлы сталидостаточно большой.Затем я реализовал TStreamReader и использовал ReadLn для заполнения TStringList, используя базовый код, найденный здесь:
TStringList.LoadFromFile - Исключения с большими текстовыми файлами
Пример кода:
//MyStringList.LoadFromFile(filename);
Reader := TStreamReader.Create(filename, true);
try
MyStringList.BeginUpdate;
try
MyStringList.Clear;
while not Reader.EndOfStream do
MyStringList.Add(Reader.ReadLine);
finally
MyStringList.EndUpdate;
end;
finally
Reader.Free;
end;
Это прекрасно работало до тех пор, пока файлы, которые мне нужно было обработать, не стали большими (~ 7 миллионов строк +).Похоже, что TStringList становится настолько большим, что не хватает памяти.Я говорю «появляется», так как на самом деле у меня нет доступа к файлу, который запускается, и все данные об ошибках предоставляются моим клиентом по электронной почте, что еще более усложняет эту проблему, поскольку я не могу просто отладить ее в IDE.
Код скомпилирован 32-битным, и я не могу использовать 64-битный компилятор.Я не могу включить систему базы данных или тому подобное.К сожалению, у меня есть некоторые жесткие ограничения.Мне нужно загружать каждую строку для поиска шаблонов и сравнивать эти строки с другими строками для поиска «шаблонов в шаблонах».Я извиняюсь за то, что здесь очень расплывчато.
Суть в следующем - есть ли способ получить доступ к каждой строке в текстовом файле без использования TStringList, или, возможно, лучший способ обработки памяти TStringList?
Может быть, есть способ загрузить определенный блок строк из StreamReader в TStringList (например, прочитать в первых 100 000 строк и обработать, следующие 100 000 строк и т. Д.) Вместо всего сразу?Я думаю, что мог бы тогда написать что-нибудь, чтобы справиться с возможными «межблочными» шаблонами.
Заранее благодарен за любую помощь и предложения!
***** РЕДАКТИРОВАНИЕ С ОБНОВЛЕНИЕМ *****
Хорошо, вот базовое решение, которое мне нужно реализовать:
var
filename: string;
sr: TStreamReader;
sl: TStringList;
total, blocksize: integer;
begin
filename := 'thefilenamegoeshere';
sl := TStringList.Create;
sr := TStreamReader.Create(filename, true);
sl.Capacity := sr.BaseStream.Size div 100;
total := 0; // Total number of lines in the file (after it is read in)
blocksize := 10000; // The number of lines per "block"
try
sl.BeginUpdate;
try
while not sr.EndOfStream do
begin
sl.Clear;
while not (sl.Count >= blocksize) do
begin
sl.Add(sr.ReadLine);
total := total + 1;
if (sr.EndOfStream = true) then break;
end;
// Handle the current block of lines here
end;
finally
sl.EndUpdate;
end;
finally
sr.Free;
sl.Free;
end;
end;
У меня есть тестовый код, который я буду использовать для уточнения своих подпрограмм, но, похоже, этобыть относительно быстрым, эффективным и достаточным.Я хочу поблагодарить всех за их ответы, которые заставили меня поджечь серое вещество!