Про копирование
немного про копирование файлов. сколькими же способами можно скопировать файл?
способ №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;