Как получить содержимое папки
Сегодня мы решим простую, но часто возникающую, особенно перед начинающими
программистами задачу получения содержимого папки. Здесь важно понять принцип, потому
напишем небольшой тестовый пример консольного приложения, которое будет выводить
дерево папки (аналог команды tree /f).
Заходим в меню File > New > Other... и на закладке New выбираем Console application.
В программу будем передавать единственной параметр - имя папки. Вытащим его:
program FolderScan;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
var
FolderName: String;
procedure WritelnToConsole(const Str: String);
var
ResultStr: String;
begin
SetLength(ResultStr, Length(Str));
CharToOem(PAnsiChar(Str), PAnsiChar(ResultStr));
Writeln(ResultStr);
end;
begin
if ParamCount > 0 then
begin
FolderName := ParamStr(1);
if DirectoryExists(FolderName) then
begin
// Здесь будем вызывать метод получения содержимого.
end
else
WritelnToConsole('Заданная папка не найдена.');
end
else
WritelnToConsole('Имя папки не задано.');
end.
|
Итак, мы получили из параметра имя папки и проверили ее существование. Осталось
решить главную задачу.
Думаю, каждый слышал о рекурсии. Чтобы понять рекурсию, нужно понять рекурсию :) Эту
задачу мы будем решать как раз рекурсивным методом.
Напишем процедуру рекурсивного перебора содержимого папки ScanFolder:
program FolderScan;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
var
FolderName: String;
procedure WritelnToConsole(const Str: String);
var
ResultStr: String;
begin
SetLength(ResultStr, Length(Str));
CharToOem(PAnsiChar(Str), PAnsiChar(ResultStr));
Writeln(ResultStr);
end;
procedure ScanFolder(const FolderName: String);
var
SearchRec: TSearchRec;
begin
FindFirst(FolderName + '\*.*', faDirectory, SearchRec);
try
repeat
if (SearchRec.Attr and faDirectory = faDirectory) and
(SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
begin
WritelnToConsole(SearchRec.Name);
ScanFolder(IncludeTrailingPathDelimiter(FolderName) + SearchRec.Name);
end;
until FindNext(SearchRec) <> 0;
finally
SysUtils.FindClose(SearchRec);
end;
FindFirst(FolderName + '\*.*', faAnyFile and not faDirectory, SearchRec);
try
repeat
if (SearchRec.Attr and faDirectory <> faDirectory) then
WritelnToConsole(SearchRec.Name);
until FindNext(SearchRec) <> 0;
finally
SysUtils.FindClose(SearchRec);
end;
end;
begin
if ParamCount > 0 then
begin
FolderName := ParamStr(1);
if DirectoryExists(FolderName) then
ScanFolder(ExcludeTrailingPathDelimiter(FolderName))
else
WritelnToConsole('Заданная папка не найдена.');
end
else
WritelnToConsole('Имя папки не задано.');
end.
|
Всё, задача решена, но как-то некрасиво выводятся найденные данные, непонятно, что во
что вложено.
articles
design
images
097.jpg
096.jpg
099.jpg
098.jpg
101.jpg
100.jpg
103.jpg
102.jpg
104.jpg
105.jpg
106.jpg
107.jpg
index.htm
008.htm
017.htm
029.htm
030.htm
031.htm
032.htm
033.htm
034.htm
sitescripts.js
|
Доработаем процедуру, чтобы она добавляла сдвиг перед выводом имени папок и файлов:
procedure ScanFolder(const FolderName: String; Shift: String);
var
SearchRec: TSearchRec;
begin
FindFirst(FolderName + '\*.*', faDirectory, SearchRec);
try
repeat
if (SearchRec.Attr and faDirectory = faDirectory) and
(SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
begin
WritelnToConsole(Shift + SearchRec.Name);
ScanFolder(IncludeTrailingPathDelimiter(FolderName) + SearchRec.Name, Shift + ' ');
end;
until FindNext(SearchRec) <> 0;
finally
SysUtils.FindClose(SearchRec);
end;
FindFirst(FolderName + '\*.*', faAnyFile and not faDirectory, SearchRec);
try
repeat
if (SearchRec.Attr and faDirectory <> faDirectory) then
WritelnToConsole(Shift + SearchRec.Name);
until FindNext(SearchRec) <> 0;
finally
SysUtils.FindClose(SearchRec);
end;
end;
|
Соответственно изменится и вызов процедуры:
ScanFolder(ExcludeTrailingPathDelimiter(FolderName), EmptyStr)
|
Теперь список выводится красиво:
articles
design
images
097.jpg
096.jpg
099.jpg
098.jpg
101.jpg
100.jpg
103.jpg
102.jpg
104.jpg
105.jpg
106.jpg
107.jpg
index.htm
008.htm
017.htm
029.htm
030.htm
031.htm
032.htm
033.htm
034.htm
sitescripts.js
|
Вспомним еще, что есть возможность задания значения параметра по умолчанию (необязательный
параметр).
procedure ScanFolder(const FolderName: String; Shift: String = '');
|
Код самой процедуры не изменяется, а вот ее вызов в таком случае вернется к
первоначальному варианту:
ScanFolder(ExcludeTrailingPathDelimiter(FolderName))
|
Смотрите также:
|