Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Поиск в бинарном файле [D5, WinXP]


Страницы:   1 2 ... 5 6 7 8 9 10 11 12 13 14

Dimaxx ©   (2004-09-24 23:32:00) 

Сабж. Нужен алгоритм действительно быстрого поиска последовательности байт любой длины в файлах любого размера (до гигабайта). Читать кусками по-деревенски не катит. Раньше у меня был алгоритм, но с падением Фуджика все пропало.


Defunct   (2004-09-28 03:06:00) [161]

> Насколько она быстрее при работе с обычными строками (длиной 30-100 символов)

Pos будет медленнее, так как в стадартной функции Pos две пары Push/Pop в основном цикле поиска и не рассмотривается вариант отбраковки подстроки по первому и последнему символам.

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


jack128   (2004-09-28 02:42:00) [162]

Defunct ©   (28.09.04 2:29) [102]
работает более чем в два раза быстрее чем встроенная функция поиска подстроки в строке:


Ага, сели два чела, 4 дня провозились и еще и удивляются, как же у них получилась функция, которая быстрее стандартной реализации ;-)

зы Pos - не ориентирован на поиск подстроки в 1Гб файле. Насколько она быстрее при работе с обычными строками (длиной 30-100 символов)
ззы вашу функцию нужно в базу знаний отправить.


Defunct   (2004-09-28 02:29:00) [163]

> найти места где Вы не согласны с Borland и разобраться почему они всё же правы.

Знаете, не надо так свято верить в правоту Borland, функция [74] - быстрее Pos, а та к которой мы с вами в итоге пришли после усовершенствования [74] работает более чем в два раза быстрее чем встроенная функция поиска подстроки в строке: Pos. И это не первая функция на моем счету, которая доказывает, что не все решения от Borland оптимальны.

> F1 - интересно, Ctrl+Click - ещё интереснее,
Хелп сделан хорошо, здесь упреков нет.

> на самом деле, лучше вообще без except. тогда будет выведен текст исключения в сообщении
Это уж кому как, я предпочту чтобы программа умолчала об исключении вместо того чтобы показала, что исключение в ней не обрабатывается.

> почему именно не получилось. может не файл не найден а ещё что-то. хотя бы EOutOfMemory.

Ну что ж тогда увы и ах..:
<begin offtop>
.. в одном отдаленном селе Василий Певченко скачал шареварную версию нового "PuperCommander". С возгласом:
- ну наконец-то, догожданная новая версия,
Василий принялся изучать Readme файл со списоком новых возможностей и улучшений...
- О! быстрый поиск строки, сейчас посмотрю, что они там намутили, - улыбнулся Василий, который несколько лет ждал именно эту фичу.
Он задавал имя файла и ввел "смешные анеГДОТЫ" в раскрашенном поле строки поиска, к его глубочайшему удивлению на экране возникало сообщение "Да ну нет такого файла!". Василий повторял ввод имени раз за разом, раз за разом, но на экране в также весело красовалась пестрая надпись с заголовком PuperCommander, уведомляющая, что такого файла нет. Василий вспомнил, что вчера выпил не мало, об этом напиминали трясущиеся руки, и решил скопировать имя файла прямо из проводника самой модной операционки "ГунДоус" от корпорации "МодныйСофт". А на экране все также пестрилась веселая надпись "Да не найден, надо меньше пить". В гневе Василий нажал кнопку "ПЫтание" на корпусе своего модного компутера "ИВМ" от фирмы "Красночух Электроникс", замигали лампочки, в динамиках раздался приятный женский голос "подождите пожалуйста, ГунДоус приступил к первой фазе подготовки к выполнению завершения вашей работы". Василий ждал..
.....
...
..
Экран засветился, потом погас, потом опять засветился на этот раз с надписью "Красночух Электроникс БИОС, ждите", замигали лампочки. Василий потихоньку приходил в себя, он взял очередную бутылочку пива из холодильника и удобно развалился на кресле с мягкой спинкой. Наблюдая за меняющимися картинками, которыми обычно сопровождается загрузка модной системы "ГунДоус", он размышлял о том, что он самый счастливый человек на свете. Теперь у него есть "PuperCommander" и он сможет с гордостью похвастаться об этом своим друзьям. "ГунДоус" пригласил Василия ввести пароль, после чего Василий сразу же запустил "PuperCommander" ввели имя файла и.... О чудо! ни каких надписей, пестрая табличка с вопросом "смешные анеГДОТЫ найдены, показать?".
- Глючный ГунДоус, - подумал Василий, - когда уже эти олухи из корпорации "МодныйСофт" сделают что-то нормальное..
<end offtop>

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


GuAV   (2004-09-28 01:21:00) [164]

знаете, как можно узнать про флаг D, отсутсвие результата при exception и т.д. ?
посмотреть исходники VCL, найти места где Вы не согласны с Borland и разобраться почему они всё же правы.

см. мою анкету -
F1 - интересно, Ctrl+Click - ещё интереснее,

Defunct ©   (28.09.04 01:00) [99]
на самом деле, лучше вообще без except. тогда будет выведен текст исключения в сообщении, почему именно не получилось. может не файл не найден а ещё что-то. хотя бы EOutOfMemory.

или уже например что-то типа
Try
  If ConstantExists(Edit1.Text, Edit2.Text)>0 Then
     ShowMessage('Found')
  Else
     ShowMessage('Not Found');
Except
  on EInOutErrordo ShowMessage('file '+Edit1.Text+' not found');
End;

except без on следует использовать только если внутри raise; - т.е. исключение сохранится для дальнейшего использования.


Defunct   (2004-09-28 01:03:00) [165]

GuAV ©   (28.09.04 00:59) [98]
Ок, убедили, признаю - страдать фигней незачем.


Defunct   (2004-09-28 01:00:00) [166]

PS: код [97] серьезно не воспринимать, правильно должно быть так:

procedure TForm1.Button1Click(Sender: TObject);
begin
 Try
   If ConstantExists(Edit1.Text, Edit2.Text)>0 Then
      ShowMessage('Found')
   Else
      ShowMessage('Not Found');
 Except
   ShowMessage('file '+Edit1.Text+' not found');
 End;
end;


GuAV   (2004-09-28 00:59:00) [167]

Defunct ©   (28.09.04 00:56) [97]
Это похоже на уровне "повезло", попробуйте
Var Position : Int64; - глобальная переменная.


Defunct   (2004-09-28 00:56:00) [168]

> я не пробовал, но даже немного сомневаюсь что возможно получить результат в этом случае. если можете - покажите как Вы бы это делали.

Беру функцию [87]

Использую ее так:

procedure TForm1.Button1Click(Sender: TObject);
Var Position : Int64;
begin
Try
  Position := ConstantExists(Edit1.Text, Edit2.Text);
Except
End;

If Position>0 Then
   ShowMessage('Found')
Else
   ShowMessage('Not Found');
End;
end;

В Edit1 ввожу какую-то лабуду типа "sdfsdf.asdasd" в Edit2 - "Test String" возникает исключение на экране вижу "Not Found". Хотя понятно, тест синтетический проще было бы в обработчике исключения написать, что файла с таким именем нет. ;)


GuAV   (2004-09-28 00:38:00) [169]


> > более того я даже не вижу возможности им воспользоваться.
> А я вижу, когда "наплевать" на исключения, их просто проигнорируют,
> а результат функции будет верным.
> Тока не надо говорить, что так делать не правильно, сам
> знаю, но все равно делаю ;)


например если
I:=MyFunc
и в MyFunc - исключение, то в I остаётся старое значение

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


Defunct   (2004-09-28 00:32:00) [170]

GuAV ©   (27.09.04 23:58) [93]
конечно принято!

GuAV ©   (28.09.04 00:09) [94]
> в случае исключения результат функции не нужен
почему бы не перестраховаться. пусть возвращает правильный результат даже в исключительной ситуации. (нам тока спасибо скажут)

> более того я даже не вижу возможности им воспользоваться.
А я вижу, когда "наплевать" на исключения, их просто проигнорируют, а результат функции будет верным.
Тока не надо говорить, что так делать не правильно, сам знаю, но все равно делаю ;)


GuAV   (2004-09-28 00:09:00) [171]


> GuAV ©   (27.09.04 23:26) [88]
>
> Дык, в секции finally посмотрите If bufpos<0....
> и сброс перед поиском Result := FilePos

ок.
Всё же вариант [89] ничем не хуже, только проще.

 If BufPos < 0 Then Result := -1;
кстати подобный код следует размещать после until перед finally, но не в finally. дело в том, что в случае отсутствия исключения он и так выполнится. в случае исключения результат функции не нужен, более того я даже не вижу возможности им воспользоваться.


GuAV   (2004-09-27 23:58:00) [172]

сорри, Ж нажал вместо КОД
Mov  ECx, Ebx       // ECx - constant chars amount
shr  ECx, 2         // ECx - constant chars amount div 4
jz   @@SkipDTest
Repe CmpsD
Jnz  @@SkipBTest
@@SkipDTest:  
Mov  ECx, Ebx
and  ECx, 3
jz   @@Constant_Exists // two least significant bits
                       // of amount is zero so the Constant
matches
Repe CmpsB
Jz   @@Constant_Exists
@@SkipBTest:

принято ?


GuAV   (2004-09-27 23:57:00) [173]

 Mov  ECx, Ebx       // ECx - constant chars amount
 shr  ECx, 2         // ECx - constant chars amount div 4
 jz   @@SkipDTest
 Repe CmpsD
 Jnz  @@SkipBTest
@@SkipDTest:  
 Mov  ECx, Ebx
 and  ECx, 3
 jz   @@Constant_Exists // two least significant bits
                        // of amount is zero so the Constant matches

 Repe CmpsB
 Jz   @@Constant_Exists
@@SkipBTest:

?


Defunct   (2004-09-27 23:45:00) [174]

GuAV ©   (27.09.04 23:26) [88]

Дык, в секции finally посмотрите If bufpos<0....
и сброс перед поиском Result := FilePos


Defunct   (2004-09-27 23:38:00) [175]

GuAV ©   (27.09.04 23:03) [86]
принимается с поправками, а то получим нехилую ошибку при Length(Constant)<=6 и при (Length(Constant)) mod 4 = 0.


@@CompareWholeString:
  Mov  ECx, Ebx       // ECx - constant chars amount
  shr  ECx, 2         // ECx - constant chars amount div 4
  jz   @@SkipDTest
  Repe CmpsD
  Jnz  @@SkipBTest
@@SkipDTest: 
  Mov  ECx, Ebx
  and  ECx, 3
  jz   @@SkipBTest
  Repe CmpsB
  Jz   @@Constant_Exists
@@SkipBTest:
  Mov  ESi, EBp       // restore pointer to 2nd char of constant


В общем, получилось просто отлично. на том же файле (gladiator.avi) строка поиска ("01wbcb") время просмотра всего файла - 13.43 сек (было 13.71). Для больших строк конечно же ускорение будет выше.

Попробовал поиграться с размером буфера:
- 10MB скорость падает
- делаю 512Kb - скорость падает.
(Кеш L2 у меня 1Mb) потому 1Mb - оптимально как для машины на которой проводил тесты.


GuAV   (2004-09-27 23:29:00) [176]


> Поправлю, вы забыли учесть откат на Length(Constant):

Тогда
Function ConstantExists(FileName, Constant: String): Int64;
Var
Buffer  : PBuffer;
F       : File;
BufSize : Integer;
BufPos  : Integer;
Begin
New(Buffer);
try
  AssignFile(F, FileName);
  Reset(F,1);
  try
    Repeat
      Result := FilePos(F);
      BlockRead(F, Buffer^, MaxBufferSize, BufSize);
      If BufSize < Length(Constant) Then Break;
      BufPos := ConstantPos(Constant, Buffer, BufSize);
      if BufPos > 0 then
      begin
        Inc(Result, BufPos);
        Exit;
      end;
      {Inc(Result, BufSize);}
      Seek(F, FilePos(F) - Length(Constant));
    Until (BufSize<MaxBufferSize);
    Result := -1;
  finally
    CloseFile(F);
  end;
finally
  Dispose(Buffer);
end;
End;


GuAV   (2004-09-27 23:26:00) [177]


>       If BufSize >= Length(Constant) Then
>       BufPos := ConstantPos(Constant, Buffer, BufSize);
>       Result := Result + BufPos;

Result будет накапливать -1.


Defunct   (2004-09-27 23:13:00) [178]

[84]
Поправлю, вы забыли учесть откат на Length(Constant):

Function ConstantExists(FileName, Constant: String): Int64;
Var
Buffer  : PBuffer;
F       : File;
BufSize : Integer;
BufPos  : Integer;
Begin
BufPos := -1;
New(Buffer);
try
  AssignFile(F, FileName);
  Reset(F,1);
  try
    Repeat
      Result := FilePos(F);
      BlockRead(F, Buffer^, MaxBufferSize, BufSize);
      If BufSize >= Length(Constant) Then
      BufPos := ConstantPos(Constant, Buffer, BufSize);
      Result := Result + BufPos;
      Seek(F, FilePos(F) - Length(Constant));
    Until (BufPos>0) or (BufSize<MaxBufferSize);
  finally
    CloseFile(F);
  end;
finally
  If BufPos < 0 Then Result := -1;
  Dispose(Buffer);
end;
End;


GuAV   (2004-09-27 23:03:00) [179]

такой вариант принимается ?

@@CompareWholeString:
 Mov  ECx, Ebx       // ECx - constant chars amount
 shr  ECx, 2       // ECx - constant chars amount div 4
 Repe CmpsD
 Jz   @@Constant_Exists
 Mov  ECx, Ebx
 and  ECx, 3
 Repe CmpsB
 Jz   @@Constant_Exists

или наоборот, сначала B а потом D
 Mov  ECx, Ebx       // ECx - constant chars amount
 shr  EBx, 2       // EBx - constant chars amount div 4
 and  ECx, 3
 Repe CmpsB
 Jz   @@Constant_Exists
 Mov  ECx, Ebx
 Repe CmpsD
 Jz   @@Constant_Exists


GuAV   (2004-09-27 22:59:00) [180]


>  if BufPos > 0 then

BufPos => 0 или BufPos <> -1.


Страницы:   1 2 ... 5 6 7 8 9 10 11 12 13 14

Наверх

Титульная страница Поиск, карта сайта Написать письмо