Копирование большого количества файлов в Delphi

в моем приложении мне нужно скопировать более 1000 небольших файлов

вот код, который я использую, но он очень медленный Есть ли лучший способ сделать это ?

procedure Tdatafeeds.RestotreTodaysFiles;
var
  SearchRec: TSearchRec;
  FromFn, ToFn: string;
Begin
    if DirectoryExists(BackupPath1) then
    begin
      try
        if FindFirst(BackupPath1 + '*.*', (faAnyFile AND NOT(faDirectory)), SearchRec) = 0 then
        begin
          repeat
            FromFn := BackupPath1 + '' + SearchRec.name;
            ToFn := DatafeedsPath1 + '' + SearchRec.name;
            CopyFile(Pchar(FromFn), Pchar(ToFn), false);
          until FindNext(SearchRec) <> 0;
        end;
      finally
        FindClose(SearchRec);
      end;
    end;
End;

4 ответов


обязательно сходите с SHFileOperation() как было предложено выше, CopyFile слишком медленный для этого количества файлов. Похоже, вы в основном восстанавливаете всю папку, поэтому функция поиска может быть ненужной и замедлять работу дальше. Что-то вроде этого может помочь:

uses ShellApi;

function CopyDir(const fromDir, toDir: string): Boolean;
var
  fos: TSHFileOpStruct;
begin
  ZeroMemory(@fos, SizeOf(fos));
  with fos do
  begin
    wFunc  := FO_COPY;
    fFlags := FOF_FILESONLY;
    pFrom  := PChar(fromDir + #0);
    pTo    := PChar(toDir)
  end;
  Result := (0 = ShFileOperation(fos));
end;

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


можно использовать SHFileOperation() вызов API и использование подстановочного знака в имени файла структуры. Таким образом, один вызов будет использоваться для копирования всех файлов за один раз. Существует даже возможность показать прогресс (через функцию обратного вызова) и позволить пользователю отменить операцию.


Я не могу проверить ваш код прямо сейчас, но проверить это исправлено версия

    // (!) faAnyFile-faDirectory <--- this is wrong
    // we don't subtract flag values because the value will be meaningless
    if FindFirst(BackupPath1 + '\*.*', faAnyFile, SearchRec) = 0 then
    begin
      repeat
        if  not (SearchRec.Attr and faDirectory)
            And SearchRec.Name <> "."
            And SearchRec.Name <> ".." Then
        Begin
          FromFn := BackupPath1 + '\' + SearchRec.name;
          ToFn := DatafeedsPath1 + '\' + SearchRec.name;
          CopyFile(Pchar(FromFn), Pchar(ToFn), false);
        End;
      until FindNext(SearchRec) <> 0;
      FindClose(SearchRec);
    end;

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