|
Вопрос # 678/ вопрос открыт / |
|
Здравствуйте, уважаемые эксперты!
Не могу написать полную программу поиска файлов? Искал в книгах и в интернете везде только ссылки или короткие коды.
 |
Вопрос задал: Филаретов Мансур (статус: Посетитель)
Вопрос отправлен: 29 июня 2007, 18:29
Состояние вопроса: открыт, ответов: 2.
|
Ответ #1. Отвечает эксперт: Градов Ю.М.
Здравствуйте, Филаретов Мансур!
В приложении есть пример процедуры поиска и пример применения процедуры:
Приложение: Переключить в обычный режим- procedure TForm1.ScanDir(StartDir, Mask: string; List: TStrings);
- var
- SearchRec: TSearchRec;
- begin
- if Mask = '' then
- Mask := '*.*';
- if StartDir[Length(StartDir)] <> '' then
- StartDir := StartDir + '';
- if FindFirst(StartDir + Mask, faAnyFile, SearchRec) = 0 then
- begin
- repeat Application.ProcessMessages;
- if (SearchRec.Attr and faDirectory) <> faDirectory then
- List.Add(StartDir + SearchRec.Name)
- else if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then
- begin
- List.Add(StartDir + SearchRec.Name + '');
- ScanDir(StartDir + SearchRec.Name + '', Mask, List);
- end;
- until FindNext(SearchRec) <> 0;
- FindClose(SearchRec);
- end;
- end;
-
-
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- ListBox1.Items.Clear;
- ScanDir('c:', '', ListBox1.Items);
- Label1.Caption := IntToStr(ListBox1.Items.Count);
- end;
-
 |
Ответ отправил: Градов Ю.М. (статус: 8-ой класс)
Время отправки: 30 июня 2007, 01:08
|
Ответ #2. Отвечает эксперт: Матвеев Игорь Владимирович
Здравствуйте, Филаретов Мансур!
А какие файлы Вы собираетесь искать: на локальном компьютере или в сети? Как собираетесь производить проверку: по маске файла, по регулярному выражению, или по содержимому файла?
Все зависит от конкретной задачи. Банальный перебор файлов - это рекурсивная функция, использующая FindFirst/FindNext/FindClose. Но этот метод не годится для поиска файлов в сети (вернее годится, но только внутри расшаренных каталогов, но не по компьютеру вцелом и не по всей сети).
Если ведется поиск по сети - нужно сначала для каждого компьютера найти расшаренные каталоги, что делается с помощю WNetOpenEnum - в приложении функция, которая заполнит список FF (TStringList) всеми открытыми каталогами всех компьютеров в сети (привожу ее потому что она работает довольно быстро, в отличии от большинства аналогов).
Также нужно грамотно распаралеливать вычисления - если поиск в сети - на каждый компьютер по потоку, также на каждый физический диск.
В заключении могу порекомендовать компонент TFileFinder - http://www.delphiworld.harod.ru/base/tfilefinder html, я с него начинал, только имейте ввиду - в нем есть несколько ошибок (все в той же функции перечисления расшаренных каталогов при поиске по сети, замените ее на предложенную мной).
А что косается сравнения - сравнение по маске файлов - MatchesMask из Masks.pas, регулярные выражения - рекомендую модуль SynRegExpr.pas от Андрея Сорокина из SynEdit, а при поиске по содержимому следует иметь ввиду алгоритм Ахо-Корасика, поиска нескольких подстрок в строке, пожробнее на http://algolist.manual.ru/ - это будет намного быстрее последовательного поиска нескольких подстрок.
Приложение: Переключить в обычный режим- function FindComputers(pNet: PNetResource): Integer;
- const
- cbBuffer: DWORD = 16384;
- var
- hEnum, dwResult, dwResultEnum: DWORD;
- lpnrLocal: array [0..16384 div SizeOf(TNetResource)] of TNetResource;
- i: integer;
- pp : integer;
- cEntries: Longint;
- function DeleteSlash(DirName: string): string;
- begin
- if Length(DirName) = 0 then Exit;
- Result := DirName;
- if DirName[Length(DirName)] = '' then
- Result := Copy(DirName, 1, Length(DirName)-1);
- end;
- function IsNetHost(TestStr: string): Boolean;
- begin
- Result := False;
- if Copy(TestStr, 1, 2) = '\' then Result := True;
- end;
- begin
- centries := -1;
- Result := 0;
-
- pp := RESOURCE_CONTEXT;
- if pNet <> nil then pp := RESOURCE_GLOBALNET;
- dwResult := WNetOpenEnum(
- pp, // Enumerate currently connected resources.
- RESOURCETYPE_ANY, // all resources
- 0, // enumerate all resources
- pNet, // NULL first time the function is called
- hEnum // handle to the resource
- );
-
- if (dwResult <> NO_ERROR) then
- begin
- Result := -1;
- Exit;
- end;
-
- FillChar(lpnrLocal, cbBuffer, 0);
-
- i := cbBuffer;
- dwResultEnum := WNetEnumResource(hEnum, // resource handle
- DWORD(cEntries), // defined locally as -1
- @lpnrLocal, // LPNETRESOURCE
- DWORD(i)); // buffer size
-
- for i := 0 to cEntries - 1 do
- if DirectoryExists(DeleteSlash(lpnrLocal[i].lpRemoteName)) then
- begin
- FF.Dirs.Add(lpnrLocal[i].lpRemoteName);
- Inc(Result);
- end else if IsNetHost(lpnrLocal[i].lpRemoteName) then
- FindComputers(@lpnrLocal[i]);
-
- dwResult := WNetCloseEnum(hEnum);
-
- if (dwResult <> NO_ERROR) then
- Result := -1;
- end;
Мини-форум вопроса
Мини-форум пуст.
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|