Форум: "Основная";
Текущий архив: 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