Поиск текста в файлах - Самый быстрый способ?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Поиск текста в файлах - Самый быстрый способ?

Сообщение BIT » 15.01.2018 18:26:43

Здравствуйте на сегодняшний день ищу по части текста (код ниже)
Ищет но скорость медленная по сравнению c nodped++
Какие варианты правильные или быстрей того что я привел ниже?
Возможно я вообще делаю это не правильно))

Код: Выделить всё
Var
  PascalFiles, SL: TStringList;
  PascalFiles_1: string;
  f, i: integer;
  flag:boolean=false; 
..........................................................................
//Получаю все файлы в катологе
FindAllFiles(PascalFiles, 'Путь до папки', '*', True);
 
  //Начинаю поиск по части текста в файлах
  for f := 0 to PascalFiles.Count - 1 do
  begin
    if flag then //Просто затычка))
  begin
    SL.LoadFromFile(PascalFiles.Strings[f]);   //Открываем файл
    Form3.ProgressBar1.Position := f; //Прогресс бар
    for i := 0 to SL.Count - 1 do
    begin
      //Сравниваем текст из ComboBox1.Text, и текст из файла SL.Strings[i]
      if pos( UTF8LowerCase(Trim(Form3.ComboBox1.Text)), UTF8LowerCase(Trim(SL.Strings[i]))) > 0 then
      begin
       //Проверим не повторяется ли путь до файла если нет то добавим в SynEdit1
        if Trim(PascalFiles.Strings[f]) <> Trim(PascalFiles_1) then
        begin
          //Покажем путь до файла
          Form1.SynEdit1.Lines.Add('');
          Form1.SynEdit1.Lines.Add('Файл| '+PascalFiles.Strings[f]+'*');
          PascalFiles_1 := PascalFiles.Strings[f];
        end;
        //Выводим результат поиска
        Form1.SynEdit1.Lines.Add('Line ' + IntToStr(i + 1) + ':  ' +SL.Strings[i]);
      end;
    end;
  end
else
..........................................................................

Еще это все в потоке но мне как показалось скорость уменьшилась после того как я перенес это все в отдельный поток.
Аватара пользователя
BIT
новенький
 
Сообщения: 25
Зарегистрирован: 29.12.2017 15:44:58

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение pupsik » 15.01.2018 19:59:25

Убрать TStringList, использовать Stream. Можно и через readln.
Убрать pos( UTF8LowerCase(Trim(, использовать функцию бойер мура.

п.с.
В лазаре есть готовый вариант чтения файла по строкам. Вполне таки быстрый вариант.
Ещё бы учесть нюанс кодировки.
pupsik
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение BIT » 15.01.2018 20:22:07

pupsik писал(а):Убрать TStringList, использовать Stream. Можно и через readln.
Убрать pos( UTF8LowerCase(Trim(, использовать функцию бойер мура.

п.с.
В лазаре есть готовый вариант чтения файла по строкам. Вполне таки быстрый вариант.
Ещё бы учесть нюанс кодировки.

У меня поиск по части слова и за этого использую pos.
Можно ли заменить pos на, что то другое ? функцию бойер мура такого не знаю( Можно пример если он не сложный
Stream если смысл если файл грузится в TStringList?

В Lazaruse вроде нет готовой функции поиск по части слова я такого не нашел.
Аватара пользователя
BIT
новенький
 
Сообщения: 25
Зарегистрирован: 29.12.2017 15:44:58

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение pupsik » 15.01.2018 20:44:26

Stream если смысл если файл грузится в TStringList?
это вы прост не работали с файлами :). Смысл есть.
функцию бойер мура такого не знаю( Можно пример если он не сложный
что бы не сложный. Ну как сказать. Почитайте в вики что это. По поводу примера. В DC (добле командер) есть. В интернете то же есть (правда более под 1251 но и ютф8 можно найти).

В Lazaruse вроде нет готовой функции поиск по части слова я такого не нашел.
не понял. Я, вроде о чтении файла писал.
pupsik
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение olegy123 » 15.01.2018 21:37:47

BIT писал(а):Какие варианты правильные или быстрей того что я привел ниже?

Очень сильно влияет буфиризация чтения. Читать не по символьно, а в буфер большими размерами. Желательно размером с кластер.
HDD всегда дает минимум размер кластера(512 байт, но может быть больше). даже если надо считать 1 байт, по проводам уйдет 512 байт.
В системе он может быть больше но кратен (ntfs - обычно 4096 байт, но может быть больше).
Имеет смысл минимум считать по 4096 байт или кратный 4K размер например 65536 байт или даже больше.

Далее можно даже сделать конвейер, и распаралелить(до числа процессоров).
Но нужно решить вопрос склейки, когда одно слово(части) может находится в разных буферах

Добавлено спустя 8 минут 16 секунд:
BIT писал(а):В Lazaruse вроде нет готовой функции поиск по части слова я такого не нашел.

Pos
https://www.freepascal.org/docs-html/rt ... m/pos.html
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение BIT » 15.01.2018 21:49:53

pupsik писал(а):
Stream если смысл если файл грузится в TStringList?
это вы прост не работали с файлами :). Смысл есть.

Специально залес в исходник оказалось что это одно и тоже
Код: Выделить всё
Procedure TStrings.LoadFromFile(const FileName: string);
Var
        TheStream : TFileStream;
begin
  TheStream:=TFileStream.Create(FileName,fmOpenRead or fmShareDenyWrite);
  try
    LoadFromStream(TheStream);
  finally
    TheStream.Free;
  end;
end;   

Аватара пользователя
BIT
новенький
 
Сообщения: 25
Зарегистрирован: 29.12.2017 15:44:58

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение olegy123 » 15.01.2018 21:50:51

BIT писал(а):Можно ли заменить pos на, что то другое ?

Зачем?
По поводу ускорение..
имеет смысл размещать все в памяти..
[блок][блок][блок][блок][блок][блок][блок][блок]
и потом пройтись pos
Но нужно учесть что pos - Integer - т.е. есть ограничения по размеру.
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение BIT » 15.01.2018 21:54:36

olegy123 писал(а):
BIT писал(а):Можно ли заменить pos на, что то другое ?

Зачем?
По поводу ускорение..
имеет смысл размещать все в памяти..
[блок][блок][блок][блок][блок][блок][блок][блок]
и потом пройтись pos
Но нужно учесть что pos - Integer - т.е. есть ограничения по размеру.

Если вы про массив и так все кладу в него TStringList а он во временной памяти

Добавлено спустя 34 секунды:
olegy123 писал(а):
BIT писал(а):Какие варианты правильные или быстрей того что я привел ниже?

Очень сильно влияет буфиризация чтения. Читать не по символьно, а в буфер большими размерами. Желательно размером с кластер.
HDD всегда дает минимум размер кластера(512 байт, но может быть больше). даже если надо считать 1 байт, по проводам уйдет 512 байт.
В системе он может быть больше но кратен (ntfs - обычно 4096 байт, но может быть больше).
Имеет смысл минимум считать по 4096 байт или кратный 4K размер например 65536 байт или даже больше.

Далее можно даже сделать конвейер, и распаралелить(до числа процессоров).
Но нужно решить вопрос склейки, когда одно слово(части) может находится в разных буферах

Добавлено спустя 8 минут 16 секунд:
BIT писал(а):В Lazaruse вроде нет готовой функции поиск по части слова я такого не нашел.

Pos
https://www.freepascal.org/docs-html/rt ... m/pos.html

Для меня это очень сложно что вы описали)
Pos я использую имелось введу поиск сразу в файле по части слова

Добавлено спустя 15 минут 29 секунд:
Замедляется поиск если фай не нетипизированны в типизированных файлах поиск по скорости идентичный с nodped++
Последний раз редактировалось BIT 15.01.2018 22:13:24, всего редактировалось 1 раз.
Аватара пользователя
BIT
новенький
 
Сообщения: 25
Зарегистрирован: 29.12.2017 15:44:58

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение olegy123 » 15.01.2018 22:10:44

BIT писал(а):Если вы про массив и так все кладу в него TStringList
про TStringList, я могу ошибаться, но он форматирует raw данные, т.е. делает обработку до строк, где каждая строка это отдельный Items.Я могу ошибаться.
Если это так то процессорное время тратится на генерацию Items.

BIT писал(а):Для меня это очень сложно что вы описали)
Все просто, в железе, т.е HDD не может физически выдать 1Байт. Он сделан выдавать проциями. Поэтому если он выдает минимум 512 байт.. то не имеет смысла читать с него по 1байту.. Иначе ему придется 512 раз выдать по 512байт чтобы вы считали по 1 байту..
Представте, что вы читаете по буквам, а потом в голове формируете слова.. не проще читать по словам? А лучше предложениями или даже абзацами.. страницами.
Ровно также устроенно железо, минимум что может считать 1кластер. Он записывает 1байт тоже целым кластером. Считывает целый кластер, меняет байт и записывает весь кластер.
Правда в SSD может быть иной подход.
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение BIT » 15.01.2018 22:19:00

olegy123 писал(а):
BIT писал(а):Если вы про массив и так все кладу в него TStringList
про TStringList, я могу ошибаться, но он форматирует raw данные, т.е. делает обработку до строк, где каждая строка это отдельный Items.Я могу ошибаться.
Если это так то процессорное время тратится на генерацию Items.

BIT писал(а):Для меня это очень сложно что вы описали)
Все просто, в железе, т.е HDD не может физически выдать 1Байт. Он сделан выдавать проциями. Поэтому если он выдает минимум 512 байт.. то не имеет смысла читать с него по 1байту.. Иначе ему придется 512 раз выдать по 512байт чтобы вы считали по 1 байту..
Представте, что вы читаете по буквам, а потом в голове формируете слова.. не проще читать по словам? А лучше предложениями или даже абзацами.. страницами.
Ровно также устроенно железо, минимум что может считать 1кластер. Он записывает 1байт тоже целым кластером. Считывает целый кластер, меняет байт и записывает весь кластер.
Правда в SSD может быть иной подход.

Я так понимаю TStringList в нем item с строкой pos ищет в этой строке заданные символы (часть текста) если нет совпадений берет следующий item
Протестировал и понял, что именно pos замедляет работу и поиск в нетипизированны файлах

Может POS научить обходить стороной нетипизированне символы? имею введу dll dat exe и тп

Проверил в nodped++ теперь понял почему он ищет быстрей меня)) он пропускает все символы в нетипизированне файлах как я и предполагал теперь надо найти способ как и мне научится это делать))
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось BIT 15.01.2018 22:40:30, всего редактировалось 1 раз.
Аватара пользователя
BIT
новенький
 
Сообщения: 25
Зарегистрирован: 29.12.2017 15:44:58

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение pupsik » 15.01.2018 22:38:13

Специально залес в исходник оказалось что это одно и тоже
чтение "строками" <> загрузкой "сразу". Но это не важно.
Вы спросили как. Вам попытались объяснить. В общем... у вас всё работает? Не трогайте.

п.с.
Может POS научить обходить стороной нетипизированне символы? имею введу dll dat exe и тп
Если я скажу что в FileUtils есть "определялка" текстовый файл или нет, вам это поможет?
pupsik
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение olegy123 » 15.01.2018 22:42:19

Эх.. чё то меня понесло, я то думал вы тексты гигабайтами читаете.

Код: Выделить всё
sl:TStringList;
..
index:=pos(substr,sl.text);


Код: Выделить всё
strS:=TStringStream.Create;
strS.LoadFromFile("filename.txt");
index:=pos(substr,strS.dataString);


BIT писал(а):Может POS научить обходить стороной нетипизированне символы?
что значить "нетипизированны файлах"? все файлы это массив байтов..
в старое время, для обработки файла использовались файловые переменные, к которым был разных подход в обработке. Их типитизировали, структуризировали. Ушли от такого написания:
var f:text;
assign(f,"text.txt");

проще f:text; заменить на ss:TStringStram
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение BIT » 15.01.2018 22:42:59

pupsik писал(а):
Специально залес в исходник оказалось что это одно и тоже
чтение "строками" <> загрузкой "сразу". Но это не важно.
Вы спросили как. Вам попытались объяснить. В общем... у вас всё работает? Не трогайте.

п.с.
Может POS научить обходить стороной нетипизированне символы? имею введу dll dat exe и тп
Если я скажу что в FileUtils есть "определялка" текстовый файл или нет, вам это поможет?

Ну как не трогать кто будет пользоваться поиском скажу фууу.... у тебя программа тормазнутая в nodped++ все работает намного быстрей)))

Добавлено спустя 6 минут 26 секунд:
olegy123 писал(а):Эх.. чё то меня понесло, я то думал вы тексты гигабайтами читаете.

Код: Выделить всё
sl:TStringList;
..
index:=pos(substr,sl.text);


Код: Выделить всё
strS:=TStringStream.Create;
strS.LoadFromFile("filename.txt");
index:=pos(substr,strS.dataString);


BIT писал(а):Может POS научить обходить стороной нетипизированне символы?
что значить "нетипизированны файлах"? все файлы это массив байтов..
в старое время, для обработки файла использовались файловые переменные, к которым был разных подход в обработке. Их типитизировали, структуризировали. Ушли от такого написания:
var f:text;
assign(f,"text.txt");

проще f:text; заменить на ss:TStringStram

Не файлы маленькие с текстом по несколько килобайт
На данный момент я также делаю как вы написали только не в потоке А В ПОТОКЕ Шутка))) Просто я наверно не понимаю чем отличается TStringStream от TFileStream ?
Аватара пользователя
BIT
новенький
 
Сообщения: 25
Зарегистрирован: 29.12.2017 15:44:58

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение olegy123 » 15.01.2018 22:50:13

BIT писал(а):он пропускает все символы в нетипизированне файлах
?? Он не пропускает их.. он не перебирает каждый Items а читает весь Raw

Добавлено спустя 2 минуты 45 секунд:
BIT писал(а):Не файлы маленькие с текстом по несколько килобайт

тогда как измеряете скорость?там все мгновенно происходит.
Может проблема в измерениях?
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Поиск текста в файлах - Самый быстрый способ?

Сообщение pupsik » 15.01.2018 22:56:33

Ну как не трогать кто будет пользоваться поиском скажу фууу
тогда почитайте как искать в файлах. Посмотрите как сделано в открытых программах. В самом лазаре не советую. Там на stringlist и тухнет на файлах более 10 метров. Хотя и полезно посмотреть.
Тем более в нотепаде есть исходники. Для ознакомления полезно.

п.с.
olegy123 TStringStream лучше заменить memorystream. Плюс уйти от pos. Но это не важно :)
pupsik
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Vlad04 и гости: 33

Рейтинг@Mail.ru