Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.05.22;
Скачать: [xml.tar.bz2];

Вниз

Поиск последовательности байт в файле.   Найти похожие ветки 

 
3223(jab)   (2003-05-07 10:55) [0]

Люди добрые, помогите ускорить процесс поиска определённой последовательности байт в файле.

Осуществляю поиск следующим образом:

procedure TForm1.Button1Click(Sender: TObject);
var
i:Integer;
FStream:TFileStream;
begin
Button1.Enabled:=False;
FStream:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
StatusBar1.SimpleText:="Длинна файла="+IntToStr(FStream.Size-1);
//
for i:=0 to FStream.Size-1 do begin
FStream.Position:=i;
FStream.Read(data,sizeof(data));
ProgressBar1.Max:=FStream.Size-1;
ProgressBar1.Position:=i;
find(i);
Application.ProcessMessages;
end;
//
ListView1.Items.Add.Caption:=IntToStr(FileSize(f1)-1);
FStream.Free;
Button1.Enabled:=True;
end;

procedure TForm1.find(i:Integer);
begin
case data of
$57: a:=1;
$41: a:=a+1;
$56: a:=a+1;
$45: begin if a=3 then ListView1.Items.Add.Caption:=IntToStr(i-11); a:=0; end
else a:=0; end;
end;

Очень медленно получается! Может есть примерчик или какими функциями можно воспользоваться или вообще реально ускорить поиск?


 
evvcom   (2003-05-07 11:03) [1]

Читаешь в буфер и AnsiStrPos


 
Leshiy   (2003-05-07 11:06) [2]

Читать из файла блоками больше чем 1 байт.


 
ASMiD   (2003-05-07 11:17) [3]

Leshiy прав
Сначала читаеш все данные из потока в память, и только потом начинаеш проверять.
А то - нард жалко.


 
evvcom   (2003-05-07 11:27) [4]


> Сначала читаеш все данные из потока в память

Все может и не получиться. Но в цикле, например, по 64 тыс. байт - нормально. Только учти, что искомая комбинация может попасть на конец текущего/начало следующего блока, поэтому читать, например, по 64004 байт, а потом возвращаться на 4 байта назад (такая вроде длина искомой строки) и следующий блок читать с позиции 64000.


 
ASMiD   (2003-05-07 11:45) [5]

А что нельзя считать все сразу?


 
evvcom   (2003-05-07 11:57) [6]


> А что нельзя считать все сразу?

А если файл на Гиг? Ведь возможно и такое. И такая маленькая программка сожрет всю память!


 
3223(jab)   (2003-05-07 12:31) [7]

У меня файлы по 500 -700 Мегобыйт.

>Читаешь в буфер и AnsiStrPos

Это как понимать? Ну читать в буфер можно я так понял
var
buf:^Byte;
begin
GetMem(buf,64004);
...
FreeMem(buf,64004);
end;
А куда приделать AnsiStrPos ??????


 
3223(jab)   (2003-05-07 12:37) [8]

Мне добрые люди посоветовали воспользоваться АПИ функциями:
CreateFileMapping, MapViewOfFile

Пока ничего хорошего из этого не вышло! Может кто чего подскажет по этому поводу?


 
evvcom   (2003-05-07 12:51) [9]

var
Buf: array[0..64004] of Char;
pPos: PChar;
begin
// ... цикл пока не конец файла
FStream.Read(Buf, sizeof(Buf));
pPos := AnsiStrPos(Buf[0], #57#41#56#45);
if Assigned(pPos) then begin
// Ура нашел!
// Break или Exit
end;
// цикл
end;


А с CreateFileMapping, наверное, действительно побыстрее получится, избавишься от двойного копирования, но дальнейший поиск все равно так же. Описаны эти функции то ли в книге Джефри Рихтер "Windows для профессионалов", то ли в книге Тейксера и Пачеко. В любом случае хорошие книги, поищи.


 
3223(jab)   (2003-05-07 14:10) [10]

to evvcom
Спасибо за разьяснение!
А книги конечно хорошие и стоят они наверно не плохо! :)

Гдеб их на шару урвать...


 
3223(jab)   (2003-05-07 14:15) [11]

Джеффри РИХТЕР "Windows для профессионалов" - нашел!
Каму надо могу сказать где искать.
Искать на страничке у Анатолия Подгорецкого, за что ему огромное спасибо! :)


 
MBo   (2003-05-07 14:15) [12]

>3223(jab)

Загляни в
http://delphimaster.net/view/1-1052141053/
и под себя модифицируй


 
ND   (2003-05-07 16:42) [13]

>evvcom
Код хороший, только чуть нужно подправить .
Вот только - как найти номер байта начиная с которого совпадает с которого появляется в файле эта послед-ть байтов.

Задача как правило именно такая.

Все равно получается нужен перебор или можно как-то вычислить из модифицировав твой код.


 
3223(jab)   (2003-05-07 16:50) [14]

to evvcom
Да действительно! ND прав! Мне не удалось определить адрес. + заругалось на pPos:=AnsiStrPos(Buf[0],#57#41#56#45); [Error] Unit1.pas(239): Incompatible types: "Char" and "PChar" - это я обойти смог pPos:=AnsiStrPos(PChar(Buf[0]),#57#41#56#45); только какая то белеберда вышла!
to MBo спасибо, посмотрю, попробую!


 
evvcom   (2003-05-07 16:57) [15]


> Вот только - как найти номер байта начиная с которого совпадает
> с которого появляется в файле эта послед-ть байтов.

Посчитать! Возвращает PСhar на найденную последовательность. Из этого DWORD(Pchar) отнять DWORD(@Buf[0]) получишь индекс позиции. Может DWORD(Buf) тоже пройдет (сомнения)?.. Адреса сравнивать нельзя - компилятор ругается, а после приведения типов к Integer или DWORD можно.


 
evvcom   (2003-05-07 17:04) [16]


> Да действительно! ND прав! Мне не удалось определить адрес.
> + заругалось на pPos:=AnsiStrPos(Buf[0],#57#41#56#45); [Error]
> Unit1.pas(239): Incompatible types: "Char" and "PChar" -
> это я обойти смог pPos:=AnsiStrPos(PChar(Buf[0]),#57#41#56#45);
>

Прошу прощения, спутал с Move(var Buf; ...). Здесь ведь PChar.
Здесь надо pPos:=AnsiStrPos(Buf,#57#41#56#45); или pPos:=AnsiStrPos(@Buf[0],#57#41#56#45); но по-моему и первый вариант пройдет.


 
evvcom   (2003-05-07 17:08) [17]

Еще может возникнуть проблема. Если в файле встретится нулевой байт, то для PChar - это конец строки. На нем AnsiStrPos прекратит поиск.


 
ND   (2003-05-07 17:18) [18]

>evvcom

>Посчитать! Возвращает PСhar на найденную последовательность. Из >этого DWORD(Pchar) отнять DWORD(@Buf[0]) получишь индекс >позиции. Может DWORD(Buf) тоже пройдет (сомнения)?.. Адреса >сравнивать нельзя - компилятор ругается, а после приведения >типов к Integer или DWORD можно.

Не пойму объясни подробнее.


 
3223(jab)   (2003-05-07 17:49) [19]

Эээ, а как это сделано в Hex эдиторах? (16 ричных просмотрщиках)


 
default   (2003-05-07 18:56) [20]

можно сделать вроде этого:
читаете данные из файла "как послед-ть символов"
и среди них быстрым алгоритмом поиска подстроки в строке
производите поиск
только станд-ые ф-ии не используйте типа Pos, IndexOf(в потомках TStrings)...
это всё - обычный перебор - и для твоих размеров файлов с таким "крутым"
методом поиска программа будет очень тормозной...
при этом учитывай замечание evvcom © (07.05.03 11:27)


 
vgb   (2003-05-07 20:00) [21]

To 3223(jab)

> Джеффри РИХТЕР "Windows для профессионалов" - нашел!
> Каму надо могу сказать где искать.
> Искать на страничке у Анатолия Подгорецкого, за что ему
> огромное спасибо! :)

Link ne dadite?
A to zadolbalsa iskat"


 
evvcom   (2003-05-07 23:33) [22]


> А книги конечно хорошие и стоят они наверно не плохо! :)
>
> Гдеб их на шару урвать...

Стоят неплохо, но есть и нахаляву http://delphiplus.nagano.ru/DocsDelphi5.html (Тейксейра и Пачеко)


 
evvcom   (2003-05-08 08:03) [23]

>
> >Посчитать! Возвращает PСhar на найденную последовательность.
> Из >этого DWORD(Pchar) отнять DWORD(@Buf[0]) получишь индекс
> >позиции. Может DWORD(Buf) тоже пройдет (сомнения)?.. Адреса
> >сравнивать нельзя - компилятор ругается, а после приведения
> >типов к Integer или DWORD можно.
>
> Не пойму объясни подробнее.

pPos := AnsiStrPos(Buf, #57#41#56#45);
if Assigned(pPos) then begin
// Ура нашел!
iPosIndex := DWORD(pPos) - DWORD(Buf); // Приведение адресов к DWORD, так как PChar, Pointer и др.адресные типы нельзя сравнивать, складывать и т.д.
// Break или Exit
end;</CODE


 
ND   (2003-05-08 12:52) [24]

>evvcom

я пробовал

pPos := AnsiStrPos(Buf, #57#41#56#45);
if Assigned(pPos) then begin
// Ура нашел!
iPosIndex := DWORD(pPos) - DWORD(Buf); // Приведение адресов к DWORD, так как PChar, Pointer и др.адресные типы нельзя сравнивать, складывать и т.д.
// Break или Exit
end;</CODE

dword(pPos) и DWORD(Buf) - на моем компе всегда одни те же значения не зависящие от того где найдена послед-ть.

Ppos - это же по сути переменная - а значит по сути копируется
найденная послед-ть байтов и соответственно по ней адреса вхождения не найдешь


 
evvcom   (2003-05-08 14:12) [25]

2ND: Прогнал сейчас в Дельфях то, что писал выше. Единственное, что все же поправил, это DWORD(Buf) заменил на DWORD(@Buf[0]), о чем я выше и выражал сомнения. Итого код абсолютно работоспособный:
procedure TForm1.Button1Click(Sender: TObject);
var
Buf: array[0..100] of Char;
pPos: PChar;
iPosIndex: Integer;
begin
Buf := "абракадабра непонятная "#57#41#56#45" абракадабра непонятная";
pPos := AnsiStrPos(Buf, #57#41#56#45);
if Assigned(pPos) then begin
// Ура нашел!
iPosIndex := DWORD(pPos) - DWORD(@Buf[0]);
// дальнейшие вычисления с использованием iPosIndex
end;
end;

Только оптимизацию из опций проекта убери, а то соптимизирует, что до iPosIndex не доберешься по причине его дальнейшего неиспользования в данном примере.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.05.22;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.012 c
14-70431
l2t_guest
2003-04-29 17:18
2003.05.22
Как сэмулировать разрешение экрана не переключая режима?


1-70243
Comp
2003-05-12 09:26
2003.05.22
Как заставить дочернюю форму MiDI не появляться???


14-70476
Den
2003-05-03 09:14
2003.05.22
Цифры в слова


14-70511
NA
2003-05-05 00:28
2003.05.22
Рандомизация всей страны, или Хаотичные движения мышью


3-70112
Oleg_delphin
2003-04-29 16:51
2003.05.22
Вставка в dbf используя Агрегаты





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский