Delphi programming blog
Источник: http://teran.karelia.pro/articles/item_4404.html
 

Про копирование

Опубликовано 14.03.2010 г. 19:03

немного про копирование файлов. сколькими же способами можно скопировать файл?

способ №1: с использованием функции shFileOperation

procedure copy_shellFileOp(target : string);
var  fop : TSHFileOpStruct;
begin
    zeroMemory(@fop,sizeof(fop));
    fop.Wnd := 0;
    fop.wFunc := FO_COPY;
    fop.pFrom := pChar(sourceFile+#0#0);
    fop.pTo := pChar(target+#0#0);
    fop.fFlags := FOF_ALLOWUNDO;
    SHFileOperation(fop);
end;

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

способ №2: использование copyFile

procedure copy_copyFile(target : string);
begin
    copyFile(sourceFile,pChar(target),false);
end;

перезаписывает файл при совпадении имен. вызывается из kernel32

способ №3. использование методов TFile

procedure copy_tfile(target:string);
begin
    TFile.Copy(sourceFile,target);
end;

вообще, данная функция в итоге сводится к copyFile, при совпадении имен вызывает исключительную ситуацию.

способ №4. readFile/WriteFile

procedure copy_readwrite(target:string);
const N = 1024*500;
var nRead,nWritten : cardinal;
     fs : TOFStruct;
     inf,outf : hFile;
begin
     inf  := openFile(sourceFile,fs,OF_READ);
     outf := openFile(pAnsiChar(target),fs,OF_CREATE or OF_WRITE);
     while readFile(inf,buffer, N, nRead, nil) and (nRead > 0) do begin
          writeFile(outf,buffer,nRead,nWritten,nil);
     end;
     CloseHandle(inf);
     CloseHandle(outf);
end;

изменение размера буфера немного влияет на скорость. вызывается из kernel32

способ №5. Использование blockRead/blockWrite

procedure copy_blockread(target:string);
const N = 1024*256;
var buffer : array[0..N] of char;
     numRead,numWritten : integer;
     inf,outf : FILE;
begin
     assignFile(inf,sourceFile);
     assignFile(outf,target);
     reset(inf,1);
     rewrite(outf,1);
     repeat
          System.BlockRead(inf, Buffer, SizeOf(Buffer), NumRead);
          BlockWrite(outf, Buffer, NumRead, NumWritten);
     until (numRead =0 ) or (numRead  numWritten);
     closefile(inf);
     closefile(outf);
end;

сводится к ReadFile предыдущего примера.

способ №6. использование интерфейса IFileOperation

procedure copy_IFileOperation(target:string);
var ifo : IFileOperation;
    s,d : IShellItem;
begin
    ifo := createComObject(CLSID_FileOperation) as IFileOperation;

    shCreateItemFromParsingName(sourceFile,nil,IID_IShellItem,s);
    SHCreateItemFromParsingName(pChar('d:\'),nil,IID_IShellItem,d);

    ifo.CopyItem(s,d,pChar(target),nil);
    ifo.PerformOperations;

    ifo := nil;
end;

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

procedure TMainForm.testCopyButtonClick(Sender: TObject);
var num : byte;
    copyProc : procedure (target:string);
    timer : TStopWatch;
    sf : hFile;
    fs : TOFStruct;
    size : integer;
    speed  : real;
    time : integer;
begin
    sf := openFile(sourceFile,fs,OF_READ);
    size := getFileSize(sf,nil);
    closeHandle(sf);

    memo.Clear;
    for num in [0..5] do begin
        case num of
            0 : copyProc := copy_shellFileOp;
            1 : copyProc := copy_copyFile;
            2 : copyProc := copy_tfile;
            3 : copyProc := copy_readwrite;
            4 : copyProc := copy_blockread;
            5 : copyProc := copy_IFileOperation;
        end;
        timer := TStopWatch.StartNew;
        copyProc(destFile + intToStr(num));
        time := timer.ElapsedMilliseconds;
        speed := size/1024/1024 /  time * 1000;

        memo.Lines.Add( Format('%d: %.1f MBytes/s (%d sec)',[num,speed,round(time/1000)])) ;
        sleep(1000);
        application.ProcessMessages;

    end;
end;

Комментарии

Нет комментариев
- Имя
- e-mail*
- Сайт
вы можете использовать теги [i],[b],[code],[quote]
Дополнительно