2009-10-19 37 views
6

Trong ứng dụng của tôi, tôi cần phải sao chép hơn 1000 file nhỏSao chép nhiều tập tin trong Delphi

Dưới đây là đoạn code Tôi đang sử dụng nhưng nó là rất chậm Có cách nào tốt hơn để làm điều này?

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

Sao chép nhiều tệp nhỏ có thể xảy ra các sự cố I/O, đặc biệt là với các đĩa chậm hơn. Người đứng đầu đĩa phải di chuyển rất nhiều để tìm kiếm các tệp và tìm không gian trống để sao chép chúng. Nếu bạn sao chép các tệp đó từ dòng lệnh, hệ thống có nhanh hơn không? –

Trả lời

10

Chắc chắn đi với SHFileOperation() như đề xuất ở trên, CopyFile là cách quá chậm đối với nhiều tập tin . Có vẻ như bạn về cơ bản đang khôi phục toàn bộ thư mục để chức năng tìm kiếm có thể không cần thiết và làm chậm những thứ chậm hơn. Một cái gì đó như thế này có thể giúp đỡ:

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; 

Chức năng này sẽ nâng cao một dấu nhắc để ghi đè lên tập tin đã có dù (có thể nó có thể được tinh chỉnh để bỏ qua mà) nhưng người dùng có thể chọn "Tất cả" vì vậy đó là một cái nhấp chuột thủ tục, nhanh hơn nhiều, có thanh tiến trình và có thể bị hủy nếu muốn.

+1

Hãy xem các cờ ** FOF_NOCONFIRMATION ** và ** FOF_NOCONFIRMMKDIR ** để tránh bất kỳ lời nhắc nào. Tham khảo: http://msdn.microsoft.com/en-us/library/bb759795%28VS.85%29.aspx – stukelly

+5

Điều gì làm cho SHFileOperation() nhanh hơn CopyFile? –

0

Có lẽ bạn có thể thử đọc một loạt tệp vào bộ nhớ và sau đó ghi tất cả vào đĩa cùng một lúc (như XCOPY). Điều đó có thể đẹp hơn trên hệ thống tập tin.

7

Bạn có thể sử dụng cuộc gọi API SHFileOperation() và sử dụng ký tự đại diện trong tên tệp của cấu trúc. Bằng cách đó, một cuộc gọi sẽ được sử dụng để sao chép tất cả các tệp trong một lần. Thậm chí còn có khả năng hiển thị tiến độ (thông qua chức năng gọi lại) và cho phép người dùng hủy hoạt động.

+0

CopyFileEx() sẽ cho phép gọi lại quá, và tôi tự hỏi nếu SHFileOperation sẽ không kết thúc gọi CopyFileEx() quá. –

+1

Đúng, nhưng AFAICS từ tài liệu MSDN 'CopyFileEx()' sẽ không cho phép ký tự đại diện cho nguồn. Vì vậy, bằng cách sử dụng 'SHFileOperation()' (hoặc giao diện 'IFileOperation' trên Vista và hơn thế nữa) sẽ thay thế vòng lặp tìm thấy tập tin. – mghie

+0

Cảm ơn - SHFileOperation() hoạt động tốt bản sao bây giờ mất vài giây - trước khi mất vài phút :) –

2

tôi không thể kiểm tra mã của bạn ngay bây giờ, nhưng hãy kiểm tra này điều chỉnh phiên bản

// (!) 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; 
Các vấn đề liên quan