Topic: Чтение данных из большого текстового файла

Добрый день.
Подскажите, как правильно организовать чтение данных из текстового файла. Размер файла может быть до 8Мб. Пробовал использовать класс TStringList, но даже при размере файла 170кб не удаётся загрузить данные из файла. Вместо TStringList загружаю данные из файла прямо в поле memo, а уже потом выполняю поиск нужных данных.
Есть ли какой-нибудь ещё способ чтения информации из файла большого объёма?

Re: Чтение данных из большого текстового файла

Приветствую.


К сожалению нет под рукой большого текстового файла, чтобы протестировать.
Получаете какое либо сообщение об ошибке?

Dmitry.

Re: Чтение данных из большого текстового файла

Сообщений об ошибке нет, делаю sl.LoadFromFile(FileName), потом проверяю количество строк sl.Count, получаю "0". Удаляю часть строк в файле, код начинает работать работать.

Re: Чтение данных из большого текстового файла

Может, свойство Count имеет тип Integer, а надо бы какой-нить WideInteger? Это вопрос к Дмитрию.

Re: Чтение данных из большого текстового файла

Пожалуйста приложите данный  текстовый файл.

Dmitry.

Re: Чтение данных из большого текстового файла

На яндекс диске:
https://yadi.sk/i/LACua8NR3aigZt

Re: Чтение данных из большого текстового файла

newusr wrote:

На яндекс диске:
https://yadi.sk/i/LACua8NR3aigZt

Протестировал, загружается полностью

procedure Form1_Button4_OnClick (Sender: TObject; var Cancel: boolean);
var
    sl: TStringList;
begin
    sl := TStringList.Create;
    sl.LoadFromFile('d:\log.txt');
    ShowMessage(sl.Count);
    sl.Free;
end;

Получаю количество строк 70723


У вас данный код не работает?

Dmitry.

Re: Чтение данных из большого текстового файла

Выяснил, что текстовый файл содержит символы в кодировке KOI-8R, если их удалить код работает.
Попробуйте скормить этот файл, а потом удалить из него последнюю строку...

Post's attachments

Attachment icon report2.txt 982 b, 575 downloads since 2018-08-31 

Re: Чтение данных из большого текстового файла

Для загрузки файлов в кодировке ANSI
используйте метод LoadFromFileAnsi

sl.LoadFromFileAnsi('d:\log.txt');
Dmitry.

Re: Чтение данных из большого текстового файла

DriveSoft wrote:

Для загрузки файлов в кодировке ANSI
используйте метод LoadFromFileAnsi

sl.LoadFromFileAnsi('d:\log.txt');

Спасибо, работает.

Re: Чтение данных из большого текстового файла

Классическая задача парсинга: имеется текстовый файл, размер очень большой, в память не загружается ( TStringList.LoadFromFileAnsi(), как и ожидалось, выдаёт Out of Memory ). Необходимо читать данные построчно.


Попробовал так:

const
  BufSize = 1;

procedure Form1_Button1_OnClick (Sender: TObject; var Cancel: boolean);
var
  FileName : string;
  TextFile : TFileStream;
  buf: Char;
  tmpLine: string;
begin
  FileName := ExtractFilePath( Application.ExeName ) + 'test.txt';
  TextFile := TFileStream.Create( FileName, fmOpenRead );
  TextFile.Seek(0,soFromBeginning);
  while not (TextFile.Position >= TextFile.Size) do
  begin
    // считать строку
    tmpLine := '';
    while not (TextFile.Position >= TextFile.Size) do begin
      TextFile.Read( buf, BufSize );
      if buf = #13 then
      begin
        TextFile.Read(buf, BufSize ); // считать #10
        break;
      end;
      tmpLine := tmpLine + buf;
    end;
    ShowMessage('Строка: '+tmpLine);
  end;
  TextFile.Free;
end;

Но оказалось, что метод TFileStream.Read передаёт в строку байт и тут же его преобразует в Юникод, что приводит к неверным результатам.

Визуальное программирование: блог и телеграм-канал.

12 (edited by vovka3003 2020-05-26 22:29:47)

Re: Чтение данных из большого текстового файла

Нет явного типа AnsiString...

Re: Чтение данных из большого текстового файла

procedure Form1_Button1_OnClick (Sender: TObject; var Cancel: boolean);
var
  TextFile : TFileStream;
  buf, s: Char;
  b : byte;
  FileName, tmpLine: string;
begin
 //  FileName := ExtractFilePath( Application.ExeName ) + 'test.txt';
  FileName := 'D:\1.txt';
  TextFile := TFileStream.Create( FileName, fmOpenRead );
  tmpLine:='';
  while TextFile.Position < TextFile.Size do
  begin
      TextFile.Read( buf, 1 );
      b := ord(buf);
      if ( b>=192 ) then s := chr(b+848) else s := chr(b);
      tmpLine := tmpLine + s;
      ShowMessage(tmpLine); // пробуем закомментить эту строку
   end;
    ShowMessage(tmpLine);
    TextFile.Free;
end;

begin
end.

Без комментариев...

Re: Чтение данных из большого текстового файла

vovka3003 wrote:

Без комментариев...

Огромное спасибо! Работает - а это главное )))

Визуальное программирование: блог и телеграм-канал.

15 (edited by vovka3003 2020-05-28 08:48:12)

Re: Чтение данных из большого текстового файла

У меня, если убрать ShowMessage - выдает какой-то мусор вместо строки...

И вот это: "if ( b>=192 ) then s := chr(b+848) else s := chr(b);" - жоский костыль которые не даст всю раскладку utf8

16 (edited by CDB 2020-05-28 09:42:49)

Re: Чтение данных из большого текстового файла

Should BUF and S be an AnsiChar instead of a char?

Don't forget a CHAR is only one single character. and only goes to 255 decimal, You have 848 being tested.

On a clear disk you can seek forever

Re: Чтение данных из большого текстового файла

CDB wrote:

Should BUF and S be a string instead of a char?

Don't forget a CHAR is only one single character.

Or cast the showmessage


procedure Form1_Button1_OnClick (Sender: TObject; var Cancel: boolean);
var
  TextFile : TFileStream;
  buf: string;
  s: char;
  b : byte;
  FileName, tmpLine: string;
begin
  FileName := ExtractFilePath( Application.ExeName ) + 'test.txt';
//  FileName := 'D:\1.txt';
  TextFile := TFileStream.Create( FileName, fmOpenRead );
  tmpLine:='';
  while TextFile.Position < TextFile.Size do
  begin
      TextFile.Read( buf, 1 );
      b := ord(buf);
      if b = $0D then
      begin
        TextFile.Read( buf, 1 );
        ShowMessage('Строка: ' + tmpLine);
        tmpLine:='';
        continue;
      end;
      if ( b>=192 ) then s := chr(b+848) else s := chr(b);
      tmpLine := tmpLine + s;
      ShowMessage('Магия!'); // если закоментровать, то работать не будет
//  ShowMessage(tmpLine); // пробуем закомментить эту строку
//  ShowMessage(buf +' - '+inttostr(b) + ' - '+s );
   end;
    ShowMessage('Строка: ' + tmpLine);
    TextFile.Free;
end;

In the documentation, the first parameter of the Read () procedure must be a string.But this does not affect the result: without a call to ShowMessage () the script does not work.

Визуальное программирование: блог и телеграм-канал.

18

Re: Чтение данных из большого текстового файла

I amended my post while you were replying - see AnsiChar for B, Buf and tmpLine

On a clear disk you can seek forever

Re: Чтение данных из большого текстового файла

CDB wrote:

Don't forget a CHAR is only one single character. and only goes to 255 decimal, You have 848 being tested.

In the MVD, string data (CHAR and STRING) is stored in Unicode, two bytes are used to store each character.

Визуальное программирование: блог и телеграм-канал.

Re: Чтение данных из большого текстового файла

Решение, подсказанное Дмитрием: использовать класс TCSV


procedure Form1_Button9_OnClick (Sender: TObject; var Cancel: boolean);
var
  FileName: string;
  CSV: TCSV;
  i: integer;
begin
  FileName := ExtractFilePath( Application.ExeName ) + 'test.txt';
  CSV := TCSV.Create;
  CSV.FieldSeparator := chr(0);
  CSV.LoadANSIFile(FileName);
  for i :=0 to CSV.LineCount - 1 do
  begin
    ShowMessage( CSV.Fields[i, 0]  );
  end;
  CSV.Free;
end;

Протестировал на файле размером 330 Мб, открывается и читает построчно.

Визуальное программирование: блог и телеграм-канал.

Re: Чтение данных из большого текстового файла

https://i.imgur.com/11Y0oNc.pngбись...

Re: Чтение данных из большого текстового файла

k245 wrote:

Решение, подсказанное Дмитрием: использовать класс TCSV


procedure Form1_Button9_OnClick (Sender: TObject; var Cancel: boolean);
var
  FileName: string;
  CSV: TCSV;
  i: integer;
begin
  FileName := ExtractFilePath( Application.ExeName ) + 'test.txt';
  CSV := TCSV.Create;
  CSV.FieldSeparator := chr(0);
  CSV.LoadANSIFile(FileName);
  for i :=0 to CSV.LineCount - 1 do
  begin
    ShowMessage( CSV.Fields[i, 0]  );
  end;
  CSV.Free;
end;

Протестировал на файле размером 330 Мб, открывается и читает построчно.

Увы.... тоже не работает, если убрать ShowMessage()...... Печалька sad

Визуальное программирование: блог и телеграм-канал.

Re: Чтение данных из большого текстового файла

vovka3003 wrote:

https://i.imgur.com/11Y0oNc.pngбись...

https://cs.pikabu.ru/post_img/2013/08/21/9/1377096971_1180276456.jpg
пока нет....

Визуальное программирование: блог и телеграм-канал.

Re: Чтение данных из большого текстового файла

https://a.d-cd.net/73aae4ds-960.jpg

Re: Чтение данных из большого текстового файла

k245 wrote:
vovka3003 wrote:

https://i.imgur.com/11Y0oNc.pngбись...

https://cs.pikabu.ru/post_img/2013/08/21/9/1377096971_1180276456.jpg
пока нет....

http://www.delphi-manual.ru/processmessages.php