Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.06.2017, 17:28   #1
greenisius
Пользователь
 
Регистрация: 06.11.2012
Сообщений: 67
По умолчанию Чтение большого файла.

Добрый день.
Нужно реализовать программу, открывающую файл (~15 ГБ) и выводящую количество символов в нём на форму раз в секунду посредством таймера.

Код:
procedure TForm1.Button2Click(Sender: TObject);
var
 inputFile: TextFile;
 List: TStringList;
 Buffer: String;
begin
  SYM_COUNT := 0;
  Timer1.Enabled := true;
  List := TStringList.Create;
  AssignFile(inputFile, Edit1.Text);
  Reset(inputFile);
  Readln(inputFile, Buffer);
  List.Add(Buffer);
  while not Eof(inputFile) do
  begin
    Readln(inputFile, Buffer);
    if  Pos('****', Buffer) <> 0 then
    begin
      Process(List);
      List.Clear;
      SYM_COUNT := SYM_COUNT + Buffer.Length;
      List.Add(Buffer);
    end
    else
    begin
      List.Add(Buffer);
      SYM_COUNT := SYM_COUNT + Buffer.Length;
    end;
  end;
  Process(List);

  CloseFile(inputFile);
  List.Free;
end;
Код:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Label1.Caption := 'Символов пройдено: ' + IntToStr(SYM_COUNT);
  Application.ProcessMessages;
end;
На форму выводится примерное 17МБ, после чего таймер затихает. Насколько я понял, прерывается чтение файла. Может кто подсказать причину?
greenisius вне форума Ответить с цитированием
Старый 24.06.2017, 20:34   #2
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Application.ProcessMessages; надо поместить в цикл, а из таймера убрать.

Код:
  while not Eof(inputFile) do
  begin
    Readln(inputFile, Buffer);
    Application.ProcessMessages;
Таймер работает на сообщениях.
Application.ProcessMessages; - переведём дословно, что получится?
Получиться команда "Приложение, обработай сообщения."
Эта команда заставляет приложение обработать очередь сообщения извлечь из неё все сообщения и если там встретиться сообщение для таймера, то вызвать его.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

Последний раз редактировалось Pavia; 24.06.2017 в 20:38.
Pavia вне форума Ответить с цитированием
Старый 26.06.2017, 08:10   #3
greenisius
Пользователь
 
Регистрация: 06.11.2012
Сообщений: 67
По умолчанию

Сделал по вашему, выставил интервал таймера 1мс. Прогресс виден, однако работа всё равно прерывается на 17МБ. Возможно, ReadLn не подходит для чтения больших файлов?
greenisius вне форума Ответить с цитированием
Старый 26.06.2017, 09:02   #4
Slym
Участник клуба
 
Регистрация: 07.12.2011
Сообщений: 1,025
По умолчанию

Цитата:
Сообщение от greenisius Посмотреть сообщение
Добрый день.
файл (~15 ГБ) и выводящую количество символов в нём на форму раз в секунду.
изобрели носитель со скоростью чтения 15гб/с?
раз в секунду никак...
кроме того смущает List.Add(Buffer); если не найдет '****' - памяти есть 15гб и 64бит сборка?

на пальцах объясни что с файлом делаешь, кроме подсчета символов, и что за магия со звездочками...
и как часто звездочки встречаются
Не стесняемся, плюсуем!

Последний раз редактировалось Slym; 26.06.2017 в 09:04.
Slym вне форума Ответить с цитированием
Старый 26.06.2017, 09:31   #5
greenisius
Пользователь
 
Регистрация: 06.11.2012
Сообщений: 67
По умолчанию Некорректная работа eof()

Открываю очень большой файл на начинаю читать из него.
В какой то момент чтение прерывается, будто бы файл окончился, однако читать из него дальше можно.

Как работает eof? Получает какой то символ конца программы? Каким образом прочитать весь файл в моей ситуации?

Код:
var
 inputFile: TextFile;
 List: TStringList;
 Buffer: String;
 i: integer;
begin
  SYM_COUNT := 0;
  Timer1.Enabled := true;
  List := TStringList.Create;
  AssignFile(inputFile, Edit1.Text);
  Reset(inputFile);
  Readln(inputFile, Buffer);
  List.Add(Buffer);
  while (not Eof(inputFile)) do
  begin
    Readln(inputFile, Buffer);
    Application.ProcessMessages;
    if  Pos('****', Buffer) <> 0 then
    begin
//      Process(List);
      List.Clear;
      List.Add(Buffer);
      SYM_COUNT := SYM_COUNT + Buffer.Length;
    end
    else
    begin
      List.Add(Buffer);
      SYM_COUNT := SYM_COUNT + Buffer.Length;
    end;
  end;
//  Process(List);


  CloseFile(inputFile);
  List.Free;
end;
greenisius вне форума Ответить с цитированием
Старый 26.06.2017, 09:36   #6
greenisius
Пользователь
 
Регистрация: 06.11.2012
Сообщений: 67
По умолчанию

Цитата:
Сообщение от Slym Посмотреть сообщение
если не найдет '****'
и как часто звездочки встречаются
Найдёт. Какой-то софт генерирует базу формата
Код:
***************
данные
данные
данные

***************
данные
данные
данные
Надо всё это дело обработать. Я не пытаюсь всё мгновенно пробежать, мне нужно просто оценивать прогресс.
greenisius вне форума Ответить с цитированием
Старый 26.06.2017, 09:39   #7
greenisius
Пользователь
 
Регистрация: 06.11.2012
Сообщений: 67
По умолчанию

Как оказалось, работа прерывается всегда на одной и той же строчке, будто бы eof() принимает завершающий символ. Но дальше читать можно и нужно. Можно сотворить костыль и зациклить eof(), но это как-то дико.
greenisius вне форума Ответить с цитированием
Старый 26.06.2017, 09:58   #8
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Забудьте уже про TextFile.
Читайте через TFileStream (говорят, ещё можно работать с большими файлами через отображение файла в память, но у меня нет такого опыта).

Последний раз редактировалось Serge_Bliznykov; 26.06.2017 в 10:28.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 26.06.2017, 10:05   #9
greenisius
Пользователь
 
Регистрация: 06.11.2012
Сообщений: 67
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
Забудьте уже про TextFile.
Читайте через TFileStream (говорят, ещё можно работать с большими файлами через отображение файла в память, но у меня нет такого опыта).
А чем мне поможет это в данном случае? Полагаю, там будет тот же системный вызов, что и для eof(), и проблема никуда не уйдет.
greenisius вне форума Ответить с цитированием
Старый 26.06.2017, 10:26   #10
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
Сообщение от greenisius Посмотреть сообщение
А чем мне поможет это в данном случае? Полагаю, там будет тот же системный вызов, что и для eof(), и проблема никуда не уйдет.
а Вы не думайте, Вы делайте.
тем более, что в TFileStream нет никакого eof()!
там есть размер (size) обрабатываемых записей.

p.s.
лирического отступление.
TextFile предназначен для обработки текстовых файлов. Текстовые файлы - это файлы, которые состоят ИСКЛЮЧИТЕЛЬНО из печатных символов.
Допускаются некоторые непечатные (служебные, переводы строк, например).
Но именно допускаются и именно некоторые.
создайте файлик, поместите туда символы с кодом 26 и 27 а потом текст и попробуйте прочитать.
Serge_Bliznykov вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Передача файла большого размера Shouldercannon Общие вопросы Delphi 12 09.03.2016 20:35
Выборка данных из большого файла linap Общие вопросы Delphi 6 01.10.2013 10:06
РазXORивание большого файла Человек_Борща Общие вопросы Delphi 9 21.05.2013 16:47
Запись большого файла на 2-ва DVD Rembo Софт 32 14.02.2009 16:02