Удалить файлы с прогрессбаром - PullRequest
0 голосов
/ 27 октября 2019

я пытаюсь сделать прогрессбар при удалении файлов вот мой код:

procedure TForm1.Timer1Timer(Sender: TObject);
var
  i:Integer; 
begin 
    i:=i+1; 
    ProgressBar.Max:=DeleteList.Count - i ; //Files = 8192       
    DeleteFile(GetIniString('List', 'File' + IntToStr(i),'','FileLists.ini'));        
    ProgressBar.Position:=ProgressBar.Position+1;
end;

Ответы [ 2 ]

3 голосов
/ 27 октября 2019

Использование потоков или 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.

0 голосов
/ 27 октября 2019

Если вы действительно хотите показать некоторый прогресс в пользовательском интерфейсе при удалении файлов, вы должны использовать потоки:

  • создать поток, который удаляет файлы
  • , а затем опрашивать прогресспотока удаления из пользовательского интерфейса

Будьте осторожны при использовании потоков, чтобы не получить доступ к частям пользовательского интерфейса (таким как индикатор выполнения) из потока удаления. По крайней мере, такие вещи должны быть синхронизированы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...