procedure GetSubDirs(const sRootDir: string; slt: TStrings);
var
srSearch: TSearchRec;
sSearchPath: string;
sltSub: TStrings;
i: Integer;
begin
sltSub := TStringList.Create;
slt.BeginUpdate;
try
sSearchPath := AddDirSeparator(sRootDir);
if FindFirst(sSearchPath + '*', faDirectory, srSearch) = 0 thenrepeatif ((srSearch.Attr and faDirectory) = faDirectory) and
(srSearch.Name <> '.') and
(srSearch.Name <> '..') thenbegin
slt.Add(sSearchPath + srSearch.Name);
sltSub.Add(sSearchPath + srSearch.Name);
end;
until (FindNext(srSearch) <> 0);
FindClose(srSearch);
for i := 0 to sltSub.Count - 1 do
GetSubDirs(sltSub.Strings[i], slt);
finally
slt.EndUpdate;
FreeAndNil(sltSub);
end;
end;
Перевод на русский язык:
Процедура Delphi, именуемая GetSubDirs, рекурсивно получает все подкаталоги в указанном корневом каталоге и добавляет их в список TStrings.
Разбивка кода:
Процедура принимает два параметра: sRootDir - строка, представляющая корневой каталог, и slt - объект TStrings, в котором будут добавлены имена подкаталогов.
Создается локальная переменная srSearch типа TSearchRec, которая используется для перебора файлов и каталогов в корневом каталоге.
Переменная sSearchPath строится путем конкатенации корневого каталога с разделителем каталогов (AddDirSeparator(sRootDir)).
Процедура использует FindFirst, чтобы найти первый файл или подкаталог, соответствующий поисковому шаблону ('*') в sSearchPath. Если не найдено файлов, она возвращает 0.
Затем процедура enters a loop, который перебирает каждый каталоговый элемент с помощью FindNext. Для каждого элемента:
Проверяется, является ли элемент подкаталогом (используя Attr и faDirectory) и не равен '.' или '..'.
Если условия выполнены, добавляется имя подкаталога в оба списка slt и локальный список TStrings, называемый sltSub.
Когда все подкаталоги будут обработаны, процедура рекурсивно вызывает себя с каждым подкаталогом в sltSub, передавая sltSub.Strings[i] как новый корневой каталог.
Наконец, она обновляет список slt и освобождает память, выделенную для sltSub.
Код хорошо структурирован и легко читаем, но есть несколько минимальных проблем:
Использование AddDirSeparator(sRootDir) можно заменить на простую конкатенацию корневого каталога с разделителем каталогов (например, \ или /) для упрощения кода.
Depth рекурсии может потенциально стать избыточной, если подкаталоги глубоко вложены. Более эффективный подход мог бы быть использованием стэка, что позволило бы лучше контролировать depth рекурсии.
Вот альтернативное решение, использующее стэк вместо рекурсивных вызовов:
В этом реализации используется TStringList, называемый Stack, для хранения подкаталогов, которые нужно обработать. Она перебирает каждый каталоговый элемент с помощью FindFirst и FindNext, а затем добавляет имя подкаталога в оба списка slt и локальный список TStrings, называемый sltSub. Затем она enters a loop, который вызывает себя с каждым подкаталогом в Stack, передавая Stack.Pop как новый корневой каталог. Это позволяет избежать избыточной рекурсии depth и может быть более эффективно для глубоко вложенных каталогов.
Процедура GetSubDirs получает все поддиректории указанной директории, рекурсивно просматривая содержимое папки и добавляя ее подпапки в список.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.