Использование потоков или IFileOperation включает довольно крутые кривые обучения. Вот несколько возможностей:
Метод TDirectory
По подсказке Джерри Доджа я решил добавить пример использования TDirectory для получения списка файлов и его обработки внапример, удалить файлы из списка.
Отображает периодическое сообщение о ходе выполнения - см. оператор if i mod 100 = 0 then
в методе ProcessFiles
. К сожалению, я не смог найти способ показать периодическое сообщение на этапе построения списка, потому что AFAIC TDirectory не предоставляет для этого необходимой ловушки.
procedure TForm2.ProcessFileList(FileList : TStringList);
var
i : Integer;
S : String;
begin
for i := 0 to FileList.Count - 1 do begin
// do something with FileList[i], e.g. delete it
S := FileList[i];
DeleteFile(S);
// Display progress
if i mod 100 = 0 then // do something to show progress
Caption := Format('Files processed: %d ', [i]);
// OR, you could use i and FileList.Count to set a trackbar % complete
end;
Caption := Format('Processed: %d files', [FileList.Count]);
end;
procedure TForm2.GetFileList(const Path : String; FileList : TStringList);
var
Files : Types.TStringDynArray;
i : Integer;
begin
Files := TDirectory.GetFiles('C:\Temp');
FileList.BeginUpdate;
try
for i:= 0 to Length(Files) - 1 do
FileList.Add(Files[i]);
finally
FileList.EndUpdate;
end;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
FileList : TStringList;
begin
FileList := TStringList.Create;
try
GetFileList('C:\Temp', FileList);
ProcessFileList(FileList);
Memo1.Lines.Text := FileList.Text;
finally
FileList.Free;
end;
end;
Должно быть очевидно, что этот способсделать это намного проще, чем использовать традиционный, специфичный для Windows метод, описанный ниже, за счет потери некоторой гибкости и иметь преимущество кроссплатформенности.
Метод IFileOperation (Windows-специфично)
API Windows имеет функциональные возможности для извлечения и обработки списка файлов, например, в каталоге, и раньше для этого была простая в использовании обертка, включая анимацию прогресса,в (античном) v.3 библиотеки SysTools от TurboPower S / Ware, но я не уверен, что эта обертка когда-либо превращалась в более позднюю версию общественного достояния. На первый взгляд, это также можно сделать с помощью интерфейса IFileOperation, но Google еще не привел простого примера. Обратите внимание, что ответ SO об этом содержит комментарий « это очень сложный API, и вам необходимо внимательно прочитать документацию ».
Я пытался сделать это сам, но вскоре вышелмоей глубины. Ответ Реми Лебо здесь на вопрос, который я написал, когда застрял, показывает, как это сделать, но метод TDirectory, описанный выше, кажется намного более простым на моем уровне квалификации.
Традиционный (D7) метод (для Windows)
По моему опыту, если вы хотите обработать только несколько сотен тысяч файлов, вы должны быть в состоянии сделать это, отображая прогресс по мере продвижения, добавляяфайлы в TStringList с последующей обработкой, с кодом в следующих строках:
procedure GetFileList(const Path : String; Recurse : Boolean; FileList : TStringList);
// Beware that the following code is Windows-specific
var
FileCount : Integer;
procedure GetFilesInner(sPath : String);
var
Path,
AFileName,
Ext: String;
Rec: TSearchRec;
Done: Boolean;
begin
Path := IncludeTrailingBackslash(sPath);
if FindFirst(Path + '*.*', faAnyFile, Rec) = 0 then begin
Done := False;
while not Done do begin
if (Rec.Name <> '.') and (Rec.Name <> '..') then begin
AFileName := Path + Rec.Name;
Ext := LowerCase(ExtractFileExt(AFileName));
if not ((Rec.Attr and faDirectory) = faDirectory) then begin
inc(FileCount);
if FileCount mod 100 = 0 then
//show progress in GUI
;
FileList.Add(AFileName)
end
else begin
if Recurse then
GetFilesInner(AFileName);
end;
end;
Done := FindNext(Rec) <> 0;
end;
FindClose(Rec);
end;
end;
begin
FileCount := 0;
FileList.BeginUpdate;
FileList.Sorted := True;
FileList.Duplicates := dupIgnore; // don't add duplicate filenames to the list
GetFilesInner(Path);
FileList.EndUpdate;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
FileList : TStringList;
FileName : String;
i : Integer;
begin
FileList := TStringList.Create;
try
GetFileList('d:\aaad7', True, FileList);
for i := 0 to FileList.Count - 1 do begin
FileName := FileList[i];
// do something with FileName, e.g. delete the file
if i mod 100 = 0 then
// display progess e.g. by
Caption := IntToStr(i);
end;
Memo1.Lines := FileList;
finally
FileList.Free;
end;
end;
В операторах if [...] mod [...] = 0 then
вы можете показать ход выполнения двух фаз, как хотите.
Кстати, этот код был предназначен только для того, чтобы вы начали. Я обязан Джерри Доджу за то, что он напомнил мне, что в последних версиях Delphi есть аналогичная встроенная функциональность посредством метода TDirectory.GetFiles, так что если вы заинтересованы в кроссплатформенном и / или приспособленном Unicode, вы быпостарайтесь лучше изучить все тонкости TDirectory и не относящихся к Windows подпрограмм, таких как TrailingPathDelim.