2009-10-19 15 views
6

Nella mia domanda ho bisogno di copiare più di 1000 file di piccole dimensioniCopia di un sacco di file in Delphi

Ecco il codice che sto usando, ma è molto lento c'è un modo migliore di fare questo?

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; 
+1

La copia di molti file di piccole dimensioni può causare problemi di I/O, in particolare con dischi più lenti. Le testine del disco devono muoversi molto per cercare i file e trovare spazio libero per copiarli. Se copi questi file dalla riga di comando, il sistema è molto più veloce? –

risposta

10

sicuramente andare con SHFileOperation() come suggerito sopra, CopyFile è troppo lento per che molti file . Sembra che tu stia fondamentalmente ripristinando un'intera cartella in modo che la funzione di ricerca possa essere non necessaria e rallentare ulteriormente. Qualcosa di simile a questo può essere di aiuto:

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; 

Questa funzione sollevare una richiesta di sovrascrivere i file esistenti anche se (forse può essere ottimizzato per saltare quella), ma l'utente può selezionare "Tutti" quindi è un one-click la procedura, molto più veloce, ha una barra di avanzamento e può essere annullata se lo si desidera.

+1

Dai un'occhiata ai flag ** FOF_NOCONFIRMATION ** e ** FOF_NOCONFIRMMKDIR ** per evitare qualsiasi richiesta. Riferimento: http://msdn.microsoft.com/en-us/library/bb759795%28VS.85%29.aspx – stukelly

+5

Cosa rende SHFileOperation() più veloce di CopyFile? –

0

Forse si potrebbe sperimentare con la lettura di un gruppo di file in memoria e poi scrivere tutti a disco in una volta (come XCOPY). Potrebbe essere più carino sul filesystem.

7

È possibile utilizzare la chiamata API SHFileOperation() e utilizzare un carattere jolly nel nome file della struttura. In questo modo sarebbe stata utilizzata una sola chiamata per copiare tutti i file in una volta sola. C'è anche la possibilità di mostrare lo stato di avanzamento (tramite una funzione di callback) e consentire all'utente di annullare l'operazione.

+0

CopyFileEx() consentirà anche il callback e mi chiedevo se SHFileOperation non terminasse di chiamare anche CopyFileEx(). –

+1

Vero, ma AFAICS dalla documentazione MSDN 'CopyFileEx()' non consentirà i caratteri jolly per l'origine. Quindi usare 'SHFileOperation()' (o l'interfaccia 'IFileOperation' su Vista e oltre) dovrebbe sostituire anche il loop di ricerca dei file. – mghie

+0

Grazie - SHFileOperation() funziona bene, la copia richiede pochi secondi - prima che ci volessero minuti :) –

2

non riesco a testare il codice in questo momento, ma controlla questo corretti versione

// (!) 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; 
Problemi correlati