6

私のアプリケーションでは、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

4 に答える 4

10

上記で提案したように、間違いなく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;

ただし、この関数は既存のファイルを上書きするプロンプトを表示します (おそらくそれをスキップするように微調整できます) が、ユーザーは「すべて」を選択できるため、ワンクリックの手順であり、はるかに高速で、プログレス バーがあり、必要に応じてキャンセルできます。 .

于 2009-10-19T13:15:03.400 に答える
7

SHFileOperation()API 呼び出しを使用して、構造体のファイル名にワイルドカードを使用できます。そうすれば、1 回の呼び出しですべてのファイルを一度にコピーできます。(コールバック関数を介して) 進行状況を表示し、ユーザーが操作をキャンセルできるようにすることもできます。

于 2009-10-19T12:41:19.113 に答える
2

あなたのコードを今すぐテストすることはできませんが、この修正版をチェックしてください

    // (!) 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;
于 2009-10-19T12:55:44.637 に答える
0

おそらく、一連のファイルをメモリに読み込んでから、一度にすべてのファイルをディスクに書き込んでみるかもしれません (XCOPY のように)。それはファイルシステム上でより良いかもしれません。

于 2009-10-19T12:41:09.477 に答える