Задача тривиальная, но всё же. Зачастую обходы делают при помощи SearchRecord, но стало интересным сделать это при помощи модуля System.IOUtils Получилось так…
Каталоги файлов и папок очень похожи по структуре на дерево или граф. Соответственно можно применить один из методов обхода для одной из этих сущностей. Я уже писал об обходе дерева в другой статье.
За основу я взял следующий рекурсивный код обхода дерева
1 2 3 4 5 6 7 8 |
Procedure TMainForm.WalkParentAndAllChildren (Node:TTreeNode); var i:integer; begin memo1.Lines.Add(Node.Text); for i := 0 to Node.Count-1 do WalkParentAndAllChildren(Node[i]); // Recurisively goes all children end; |
Если провести аналогию для файлов и папок, то получится так…
1 2 |
uses System.IOUtils, System.Types |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
procedure TGetFoldersAndFiles.GetFoldersAndFilesToSDA(dir: string; var SDAResult:TStringDynArray); var SDAFiles: TStringDynArray; SDADirs: TStringDynArray; i: Integer; SearchOption: TSearchOption; begin // SearchOption:=TSearchOption.soAllDirectories; // SDADirs:=TDirectory.GetDirectories(dir,'*.*',SearchOption); // SDAFiles:=TDirectory.GetFiles(dir,'*.*',SearchOption); AddValueToSDA(SDAResult,' '); AddValueToSDA(SDAResult,'---Dir---'); AddValueToSDA(SDAResult,dir); AddValueToSDA(SDAResult,'---'); SDADirs := TDirectory.GetDirectories(dir); SDAFiles := TDirectory.GetFiles(dir); AddValueToSDA(SDAResult,' '); AddValueToSDA(SDAResult,'---SubDirs---'); //do something with subdirs for i := Low(SDADirs) to High(SDADirs) do AddValueToSDA(SDAResult,SDADirs[i]); // do something with files AddValueToSDA(SDAResult,' '); AddValueToSDA(SDAResult,'---Files---'); for i := Low(SDAFiles) to High(SDAFiles) do AddValueToSDA(SDAResult,SDAFiles[i]); // Recursievely going on all subdirs... for i := Low(SDADirs) to High(SDADirs) do GetFoldersAndFilesToSDA(SDADirs[i], SDAResult); end; |
1 2 3 4 5 |
procedure TGetFoldersAndFiles.AddValueToSDA(var SDA: TStringDynArray; Value: string); begin SetLength(SDA, Length(SDA)+1); SDA[Length(SDA)-1]:=Value; end; |
Я использовал TStringDynArray так как эта структура быстро работает с числом элементов больше 15000, чего не скажешь о TStringList. И если в нашем каталоге большое число элементов, например C:Windows то можно и не дождаться пока он заполнится если использовать в качестве хранилища TStringList
А вот пример использования в другом модуле
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
procedure TfHTTPServer.bTestClick(Sender: TObject); var SDA:TStringDynArray; i: Integer; begin FGetFoldersAndFiles.GetFoldersAndFilesToSDA('C:\MyPhoto',SDA); for i := 0 to High(SDA) do MemoTest.Lines.Add(SDA[i]); MemoTest.Lines.Add(' '); MemoTest.Lines.Add('---Total count of elements---'); MemoTest.Lines.Add(Length(SDA).ToString()); end; |
Примечание
Есть также закомментированный кусок кода следующего вида
1 2 3 |
// SearchOption:=TSearchOption.soAllDirectories; // SDADirs:=TDirectory.GetDirectories(dir,'*.*',SearchOption); // SDAFiles:=TDirectory.GetFiles(dir,'*.*',SearchOption); |
Он собирает все файлы и каталоги из выбранной директории, но это не обход, а просто сбор того что есть в каталоге.