![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поиск папок [D7, XP, 2003]
Steep © (2007-10-27 20:53:00)что-то никак не соображу как сделать поиск подпапок по заданой папке...
т.е. поиск не файлов в папке или подпапках - а просто вывести название всех подпапок (надеюсь понятно объяснил)
пока единственное что сделал это :
задаю папку например C:\WINDOWS\system32\ в Edit1
procedure LookAll(path, mask: string);
var
sr: TSearchRec;
begin
if FindFirst(path {+ '\'} + mask, faAnyFile, sr) = 0 then
begin
repeat
if faDirectory <> 0 then //папка
begin
//пока выводим полный путь
form1.Memo1.Lines.Add(path + sr.name)
end;
until FindNext(sr) <> 0;
end;
FindClose(sr);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
LookAll( Edit1.Text, '..'); //.. - папка
end;
в итоге он находит C:\WINDOWS\system32\WINDOWS
а если писать C:\WINDOWS\system32 то C:\WINDOWS\system32\system32
чето нифига не понимаю....
Steep (2007-10-29 07:56:00) [1]Большое всем спасибо!!!
Anatoly Podgoretsky (2007-10-28 11:02:00) [2]
> Я до сих пор считал, что FindClose нужен всегда, если начат
> поиск! Т.е. Если вызвана была функция FindFirst.
> P.S.
> Из справки Д6:
> Note: FindFirst allocates resources (memory) which must
> be released by calling FindClose.
Если вернется не 0, то ресурсы не будут выделены и освобождать их не надо, а иногда и нельзя, в Д3 из-за этого возникала ошибка.
Anatoly Podgoretsky (2007-10-28 10:54:00) [3]
> не внутри этого блока это уже "глючок" (ненужный вызов будет
> делаться при не найденности ни одного файла).
Дело даже не в ненужности, а то что на определенных версиях Дельфи будет исключение.
Anatoly Podgoretsky (2007-10-28 10:53:00) [4]
> Есть ещё одна "неизящность". Имхо begin перед repeat некрасиво
> смотрится.
Он нормально смотрится и нужен, а вот FindClose не там стоит.
Германн (2007-10-28 02:56:00) [5]
> sniknik © (28.10.07 02:45) [20]
>
> > Из справки Д6:
>
> а вот из генофонда D7, проверь в D6
>
Проверил. Даже и в Д4 ты прав.
sniknik (2007-10-28 02:56:00) [6]> А почему const path?
> это означает что он никогда не меняется в этой процедуре?
ну это больше для программиста ограничение, контроль самого себя, чтоб не менял если по логике не должен. а сдесь не меняется.
но вообще, оптимизаторы сейчас хорошие они и без const тот же код сделают если изменений внутри нет. (что не значит, что писать можно абы как)
Steep (2007-10-28 02:50:00) [7]
> Потому что параметр "path" берётся из компоненты TEdit.
> А будет ли в ней существующая реально папка или не существующая,
> не проверяется. А очепятки при вводе с клавиатуры - обычное
> явление. Во втором случае не найдётся ничего. И сообщений
> об ошибках никаких. Пользователь получит ответ, что никаких
> папок нет. И даже не узнает, что это он сам ошибся!
а ну это пока он берется оттуда :)))
я для наглядности пока сам ввожу - потом будет браться стандартная системная папка из реестра.
А вобще спасибо за коментарии на будущее учту о проверках
> sniknik ©
А почему const path?
это означает что он никогда не меняется в этой процедуре?
Спасибо за помощь - не знал что можно данные из процедурки по другому забирать....
sniknik (2007-10-28 02:48:00) [8]> Все-таки не «глючок», а «неизящность» :)
как ни назови... суть я обьяснил - ненужный вызов функции.
Джо (2007-10-28 02:47:00) [9]
procedure FindClose(var F: TSearchRec);
begin
{$IFDEF MSWINDOWS}
if F.FindHandle <> INVALID_HANDLE_VALUE then
begin
Windows.FindClose(F.FindHandle);
F.FindHandle := INVALID_HANDLE_VALUE;
end;
{$ENDIF}
{$IFDEF LINUX}
if F.FindHandle <> nil then
begin
closedir(F.FindHandle);
F.FindHandle := nil;
end;
{$ENDIF}
end;
Джо (2007-10-28 02:45:00) [10]Удалено модератором
Примечание: Промахнулся :)
sniknik (2007-10-28 02:45:00) [11]> Из справки Д6:
а вот из генофонда D7, проверь в D6
function FindFirst(const Path: string; Attr: Integer; var F: TSearchRec): Integer;
const
faSpecial = faHidden or faSysFile or faVolumeID or faDirectory;
begin
F.ExcludeAttr := not Attr and faSpecial;
F.FindHandle := FindFirstFile(PChar(Path), F.FindData);
if F.FindHandle <> INVALID_HANDLE_VALUE then
begin
Result := FindMatchingFile(F);
if Result <> 0 then FindClose(F);
end else
Result := GetLastError;
end;
Германн (2007-10-28 02:38:00) [12]
> sniknik © (28.10.07 02:06) [13]
>
> > Имхо begin перед repeat некрасиво смотрится.
> мало ли как смотрится, он нужен для FindClose(sr);... а
> вот то, что FindClose(sr); не внутри этого блока это уже
> "глючок" (ненужный вызов будет делаться при не найденности
> ни одного файла).
Ты, конечно, мастер. Но гложат меня смутные сомнения. :)
Я до сих пор считал, что FindClose нужен всегда, если начат поиск! Т.е. Если вызвана была функция FindFirst.
P.S.
Из справки Д6:
Note: FindFirst allocates resources (memory) which must be released by calling FindClose.
sniknik (2007-10-28 02:32:00) [13]lines: TString s
sniknik (2007-10-28 02:31:00) [14]> не совсем понял...
проверка слева направо, и при and если первое false то прекращается.
> ну просто я не умею по другому
procedure LookAll(lines: TString; const path, mask: string);
...
Lines.Add(path + sr.name); //Полный путь
...
procedure TForm1.Button2Click(Sender: TObject);
begin
LookAll(Memo1.Lines, Edit1.Text, '*.*');
end;
Германн (2007-10-28 02:25:00) [15]
> Steep (28.10.07 02:13) [14]
>
>
> > Работать будет не всегда.
>
> а почему?
>
Потому что параметр "path" берётся из компоненты TEdit. А будет ли в ней существующая реально папка или не существующая, не проверяется. А очепятки при вводе с клавиатуры - обычное явление. Во втором случае не найдётся ничего. И сообщений об ошибках никаких. Пользователь получит ответ, что никаких папок нет. И даже не узнает, что это он сам ошибся!
Steep (2007-10-28 02:21:00) [16]
> и еще я бы переставил местами проверки, не глюк но... не
> то чтобы я такой поборник оптимизаций на спичках, но всетаки.
> if (sr.name<>'..') and (sr.name<>'.') then
не совсем понял...
> а вот это form1.Memo1.Lines уже просто "глаз режет"... не
> должно быть таких обращений в функциях, если это совершенно
> отдельная функция (типа в модуле утилит) то меняемый Lines
> должен передаваться в параметрах, если же это функция класса
> Tform1 то тогда обращение к глобальной form1 надо просто
> убрать.
ну просто я не умею по другому - хотел функцией - но там же много данных возвращается....
> Lines надо очищать перед работой.
учту..
> FileAttrs переменная лишняя.
Использовалось для иксперементов - думал что есть написать
FileAttrs := faDirectory то будет искать только папки - но такого не произошло...
уберу
Спасибо всем большое за помощь!
Steep (2007-10-28 02:13:00) [17]
> Работать будет не всегда.
а почему?
> Path := IncludeTrailingPathDelimiter (Path);
>if (sr.Attr and faDirectory) = faDirectory then
Спасибо!
> Имхо begin перед repeat некрасиво смотрится.
а.. ну там отладка была :)
sniknik (2007-10-28 02:06:00) [18]> Имхо begin перед repeat некрасиво смотрится.
мало ли как смотрится, он нужен для FindClose(sr);... а вот то, что FindClose(sr); не внутри этого блока это уже "глючок" (ненужный вызов будет делаться при не найденности ни одного файла).
и еще я бы переставил местами проверки, не глюк но... не то чтобы я такой поборник оптимизаций на спичках, но всетаки.
if (sr.name<>'..')and (sr.name<>'.')then
а вот это form1.Memo1.Lines уже просто "глаз режет"... не должно быть таких обращений в функциях, если это совершенно отдельная функция (типа в модуле утилит) то меняемый Lines должен передаваться в параметрах, если же это функция класса Tform1 то тогда обращение к глобальной form1 надо просто убрать.
и кстати, может и не по логике в данном случае, но чаще всего Lines надо очищать перед работой.
ну и д кучи, FileAttrs переменная лишняя.
Германн (2007-10-28 01:41:00) [19]
> Джо © (28.10.07 01:21) [11]
Есть ещё одна "неизящность". Имхо begin перед repeat некрасиво смотрится.
Джо (2007-10-28 01:21:00) [20]> //Если нет косой черты - добавляем
> if (path <> '') and (path[Length(path)] <> '\') then path
> := path + '\';
Path := IncludeTrailingPathDelimiter (Path);
-
> if sr.Attr and faDirectory = 16
if (sr.Attr and faDirectory) = faDirectory then