世界上最快的拷贝函数,没看懂,先放上来在说。

本文介绍了一种文件分块处理及并发写入的方法,通过将大文件分割成多个小部分并使用内存映射文件进行高效读写,进而实现快速的数据备份。此外,文章还详细介绍了使用队列管理和重试机制来提高写入过程的稳定性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

const
  MAX_PARTS = 60;
  OneMB = 1024 * 1024;
  function FastcopyFile(FileName, tofilename: string): integer;
  var SHFileOpStruct: TSHFileOpStruct;
  begin
    FileName := FileName + #0#0;
    with SHFileOpStruct do begin
      Wnd := Application.Handle;
      wFunc := FO_copy;
      pFrom := pchar(FileName);
      pTo := pchar(tofilename);
      fFlags := FOF_FILESONLY + FOF_NOCONFIRMATION + FOF_SILENT + FOF_NOERRORUI;
      // if   Recycle   then   fFlags:=fFlags   +   FOF_NOCONFIRMATION
    end;
    Result := SHFileOperation(SHFileOpStruct);
  end;
  procedure CreateS3000TAlarmTempBCPFile(pToBeSavedContent: pchar; iFileLen: Dword; BCPFileName: string);
  const
    //  S3000_TALARM_TEMP_BCP_FILE_NAME = 'S3000_tPackage_Temp.txt';
  //  LOCAL_PATH = 'C:/';
  //  SQL_SERVER_SHARED_PATH = '//aw-hp02/FilesIput/';

    MAX_PARTS = 60;
    OneMB = 1024 * 1024;
  type
    T1MBuffer = array[1..OneMB] of Byte;

  var
    FFileHandle: THandle;
    FMapHandle: THandle;
    FFileSize: Dword;
    FData: PByte;
    PData: pchar;
    FName: string;
    Ucase: bool;
    start: Dword;
    // str,
    s: string;
    i: integer;
    ThreadId: Dword;
    S3000_TALARM_TEMP_BCP_FILE_NAME: string;
    ghEvents: TwOHandlearray; //array[1..10] of
    gOverlapped: array of OVERLAPPED;
    dwNumWrite: Dword;
    ghFile: THandle;
    gBuffers: array of T1MBuffer;
    iTotalParts: Byte;
    iLeftBytes: Dword;

    function QueueWrite(nIndex: integer; dwLocation, dwAmount: Dword): integer;
    var
      maxtrycount, i: integer;
      nNumberOfBytesToWrite: Dword;
      rc: bool;
      err: Dword;
    begin

      maxtrycount := 10;
      nNumberOfBytesToWrite := dwAmount;
      ghEvents[nIndex] := CreateEvent(nil, TRUE, false, '');
      gOverlapped[nIndex].hEvent := ghEvents[nIndex];
      gOverlapped[nIndex].Offset := dwLocation;

      for i := 0 to maxtrycount - 1 do begin

        PData := pchar(FData);
        inc(PData, dwLocation);
        CopyMemory(@gBuffers[nIndex], PData, dwAmount);

        rc := writefile(ghFile, gBuffers[nIndex], nNumberOfBytesToWrite, dwNumWrite, @gOverlapped[nIndex]);
        if (rc) then begin
          Result := 1;
          break;
        end
        else begin
          err := GetLastError;
          case err of
            ERROR_INVALID_USER_BUFFER, ERROR_NOT_ENOUGH_QUOTA, ERROR_NOT_ENOUGH_MEMORY: begin
                sleep(50);
                continue;
              end;
          else ShowMessage('writefile error' + IntToStr(err));
          end;
        end;
      end;
      // break;
      Result := -1;
    end;

  begin
    S3000_TALARM_TEMP_BCP_FILE_NAME := BCPFileName;
    FName := LOCAL_PATH + S3000_TALARM_TEMP_BCP_FILE_NAME;

    if not FileExists(FName) then begin
      FFileHandle := filecreate(FName);
      fileclose(FFileHandle);
    end;

    FFileHandle := FileOpen(FName, fmOpenReadWrite);
    if FFileHandle = INVALID_HANDLE_VALUE then
      raise Exception.Create('Failed   to   open   or   create   file');
    try
      FFileSize := GetFileSize(FFileHandle, nil);
      FFileSize := MAX_PARTS * OneMB;
      FMapHandle := CreateFileMapping(FFileHandle, nil,
        PAGE_READWRITE, 0, FFileSize, nil);

      if FMapHandle = 0 then
        raise Exception.Create('Failed   to   create   file   mapping');
      try
        FData := MapViewOfFile(FMapHandle, FILE_MAP_ALL_ACCESS, 0, 0, FFileSize);
        if FData = nil then
          raise Exception.Create('Failed   to   map   view   of   file');
      finally
        CloseHandle(FMapHandle);
      end;

      try
        PData := pchar(FData);

        CopyMemory(PData, (pToBeSavedContent), iFileLen);

        inc(PData, iFileLen);
        PData^ := #0; // set the end of the file

        // iFileLen := Length(str);
        start := GetTickCount;

        ghFile := CreateFile(pchar(SQL_SERVER_SHARED_PATH + S3000_TALARM_TEMP_BCP_FILE_NAME),
          GENERIC_WRITE,
          FILE_SHARE_READ + FILE_SHARE_WRITE,
          nil,
          CREATE_ALWAYS,
          FILE_FLAG_OVERLAPPED,
          0
          );

        iLeftBytes := iFileLen mod OneMB;
        if iLeftBytes = 0 then iTotalParts := iFileLen div OneMB else iTotalParts := (iFileLen div OneMB) + 1;

        setlength(gOverlapped, iTotalParts);
        setlength(gBuffers, iTotalParts);

        if iLeftBytes = 0 then begin
          for i := 0 to iTotalParts - 1 do begin
            QueueWrite(i, i * OneMB, OneMB);
          end;
        end
        else if iTotalParts = 1 then begin
          QueueWrite(0, 0, iLeftBytes);
        end
        else begin
          for i := 0 to iTotalParts - 1 do begin
            if i <> iTotalParts - 1 then
              QueueWrite(i, i * OneMB, OneMB)

            else
              QueueWrite(i, i * OneMB, iLeftBytes)
          end;

        end;

        WaitForMultipleObjects(iTotalParts, @ghEvents, TRUE, INFINITE);
        for i := 0 to iTotalParts - 1 do begin
          // rc :=
          GetOverlappedResult(ghFile, gOverlapped[i], dwNumWrite, false);
          CloseHandle(gOverlapped[i].hEvent);
        end;

        CloseHandle(ghFile);
        //  ShowMessage(inttostr(GetTickCount - start));

      finally
        UnmapViewOfFile(FData);
      end;

    finally
      SetFilePointer(FFileHandle, iFileLen, nil, FILE_BEGIN); //reset the file size;
      SetEndOfFile(FFileHandle);
      CloseHandle(FFileHandle);
    end;

    // ShowMessage(IntToStr(gettickcount - start));
  end; 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值