⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmffile.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
   fe : TFileEntry;
   pfe: PFileEntry;

begin
    if (FPFileEntries = nil) then
       raise EMMFastFileError.Create(LoadResStr(IDS_FFNOTINIT));

    if (Name = '') or (NewName = '') then
       raise EMMFastFileError.Create(LoadResStr(IDS_FFBADFILENAME));

    if FileExists(NewName) then
       raise EMMFastFileError.Create(LoadResStr(IDS_FFDUPLICATEFILENAME));

    fe.Name := OldName;
    pfe := lfind(@fe, FPFileEntries, FPFileEntryCount^, sizeof(TFileEntry), @Compare);
    if (pfe <> nil) then
    begin
       pfe.Name := NewName;
       Change;
    end
    else raise EMMFastFileError.CreateFmt(LoadResStr(IDS_FFNOTFOUND),[OldName]);
end;

{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.ExtractFile(const Name, Path: TFileName);
var
   hOut   : THandle;
   pfh    : PFileHandle;
   Buffer : PChar;
   Bytes  : integer;
   NewFile: TFileName;

begin
    if (FPFileEntries = nil) then
       raise EMMFastFileError.Create(LoadResStr(IDS_FFNOTINIT));

    if not FileExists(Name) then
       raise EMMFastFileError.Create(LoadResStr(IDS_FFBADFILENAME));

    if (Path = '') then
       raise EMMFastFileError.Create(LoadResStr(IDS_FFBADPATH));

    Buffer := nil;
    hOut := 0;

    pfh := FileOpen(Name);
    try
       NewFile := ExpandUNCFileName(Path);

       if ExtractFileName(NewFile) = '' then
          NewFile := ExtractFilePath(NewFile) + Name;

       hOut := SysUtils.FileCreate(NewFile);
       if (hOut < 0) then
          raise EMMFastFileError.CreateFmt(LoadResStr(IDS_FFCREATEERROR),[NewFile]);

       Buffer := GlobalAllocMem(BLOCK_SIZE);

       // copy the data in the file to the new file
       while True do
       begin
          Bytes := FileRead(pfh, Buffer, BLOCK_SIZE);
          if (Bytes = 0) then break;
          if (Bytes < 0) then
             raise EMMFastFileError.Create(LoadResStr(IDS_FFREADERROR)+' "'+Name+'"');

          if SysUtils.FileWrite(hOut, Buffer^, Bytes) <> Bytes then
            raise EMMFastFileError.Create(LoadResStr(IDS_FFWRITEERROR)+' "'+NewFile+'"');

          if (Bytes < BLOCK_SIZE) then break;
      end;

    finally
       FileClose(pfh);
       SysUtils.FileClose(hOut);
       GlobalFreeMem(Pointer(Buffer));
    end;
end;

{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.Pack;
var
   i: integer;
   TempFile: String;
   hFile: THandle;
   hFileMapping: THandle;
   pBase: PChar;
   feSrc: TFileEntry;
   pfe: PFileEntryArray;
   pfeCnt: PLongint;
   NewSize: Longint;
   pos: Longint;

begin
   if (FPFileEntries <> nil) and (FNumDeleted > 0) then
   begin
      SetLength(TempFile, MAX_PATH);
      GetTempFileName(PChar(ExtractFilePath(FFileName)),'FAST'#0,0,PChar(TempFile));
      CreateFastFile(TempFile,FMaxFiles);
      try
         if not SysUtils.FileExists(TempFile) then
            raise EMMFastFileError.Create(LoadResStr(IDS_FFTEMPERROR));

         NewSize := (sizeOf(KENNUNG)-1)+2*sizeOf(Longint)+FMaxFiles*sizeOf(TFileEntry);
         for i := 0 to Count-1 do inc(NewSize, FileEntries[i].Size);

         // create a memory mapped file for the temp file
         hFile := CreateFile(PChar(TempFile), GENERIC_READ or GENERIC_WRITE,
                           FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
                           OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0);

         if (hFile = 0) or (hFile = HFILE_ERROR) then
         begin
            hFile := 0;
            raise EMMFastFileError.Create('CreateFile failed with Error Code: '+IntToStr(GetLastError));
         end;

         hFileMapping := CreateFileMapping(hFile,nil,PAGE_READWRITE,0,NewSize,nil);
         if (hFileMapping = 0) then
         raise EMMFastFileError.Create('CreateFileMapping failed with Error Code: '+IntToStr(GetLastError));

         pBase := MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);
         if (pBase = nil) then
            raise EMMFastFileError.Create('MapViewOfFile failed with Error Code: '+IntToStr(GetLastError));

         // get initial data from the memory mapped file
         pfeCnt := PLongint(pBase + sizeOf(KENNUNG)-1 + sizeOf(Longint));
         pfe := PFileEntryArray(pBase + sizeOf(KENNUNG)-1 + 2*sizeOf(Longint));

         pos := pfe[0].Offset;
         for i := 0 to Count-1 do
         begin
            try
               feSrc := FileEntries[i];
               pfe[i].Name := feSrc.Name;
               pfe[i].Offset := pos;
               pfe[i].Size := feSrc.Size;
               pfe[i].Deleted := False;

               move((FPBase + feSrc.Offset)^, (pBase + pos)^, feSrc.Size);
               inc(pos, feSrc.Size);
               inc(pfeCnt^);
            except
               raise EMMFastFileError.Create(LoadResStr(IDS_FFPACKERROR));
            end;
         end;

         // save current file position for the next entry
         pfe[pfeCnt^].Offset := pos;

         HandlesLost;

      finally
         if (hFileMapping <> 0) then
         begin
            if (pBase <> nil) then UnmapViewOfFile(pBase);
            CloseHandle(hFileMapping);
         end;
         if (hFile <> 0) then CloseHandle(hFile);
      end;

      FNumDeleted := 0;

      // now delete the old FastFile
      Done;
      SysUtils.DeleteFile(FFileName);
      SysUtils.RenameFile(TempFile,FFileName);
      Init;
   end;
end;

{-- TMMFastFile ---------------------------------------------------------}
function TMMFastFile.FileExists(const Name: TFileName): Boolean;
var
   fe: TFileEntry;
   pfe: PFileEntry;

begin
   Result := False;
   if (FPFileEntries = nil) then
      raise EMMFastFileError.Create(LoadResStr(IDS_FFNOTINIT));

   if (Name <> '') then
   begin
      fe.Name := Name;
      pfe := lfind(@fe, FPFileEntries, FPFileEntryCount^, sizeof(TFileEntry), @Compare);
      Result := (pfe <> nil);
   end;
end;

{-- TMMFastFile ---------------------------------------------------------}
function TMMFastFile.FileSize(const Name: TFileName): integer;
var
   pfh: PFileHandle;

begin
   Result := 0;
   if FileExists(Name) then
   begin
      pfh := FileOpen(Name);
      Result := pfh.Size;
      FileClose(pfh);
   end;
end;

{-- TMMFastFile ---------------------------------------------------------}
function TMMFastFile.FileOpen(const Name: TFileName): PFileHandle;
var
   fe: TFileEntry;
   pfe: PFileEntry;
   i: Longint;

begin
    Result := nil;
    if (FPFileEntries = nil) then
       raise EMMFastFileError.Create(LoadResStr(IDS_FFNOTINIT));

    if (Name = '') then
       raise EMMFastFileError.Create(LoadResStr(IDS_FFBADFILENAME));

    fe.Name := Name;
    pfe := lfind(@fe, FPFileEntries, FPFileEntryCount^, sizeof(TFileEntry), @Compare);
    if (pfe <> nil) then
    begin
       for i := 0 to FMaxHandles-1 do
       begin
          if not FPFileHandles[i].inUse then
          begin
             FPFileHandles[i].inUse := True;
             FPFileHandles[i].Pos := pfe.Offset;
             FPFileHandles[i].Size := pfe.Size;
             FPFileHandles[i].pfe := pfe;
             Result := @FPFileHandles[i];
             exit;
          end;
       end;
       raise EMMFastFileError.Create(LoadResStr(IDS_FFNOHANDLES));
    end
    else raise EMMFastFileError.CreateFmt(LoadResStr(IDS_FFNOTFOUND),[Name]);
end;

{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.FileClose(pfh: PFileHandle);
begin
   if (pfh <> nil) and (pfh.inUse = True) or pfh.pfe.Deleted then
   begin
      pfh.inUse := False;
   end;
end;

{-- TMMFastFile ---------------------------------------------------------}
function TMMFastFile.FileLock(pfh: PFileHandle; pos, size: integer): Pointer;
begin
   Result := nil;
   if (pfh = nil) or (pfh.inUse <> True) or pfh.pfe.Deleted then
      raise EMMFastFileError.Create(LoadResStr(IDS_FFBADHANDLE));

   if (Size > 0) then
   begin
      if (pos+size) > PFileEntry(PChar(pfh.pfe)+sizeOf(pfh.pfe^)).Offset then
         raise EMMFastFileError.Create(LoadResStr(IDS_FFFILEEND));
      Result := FPBase + pfh.pfe.offset + pos;
   end;
end;

{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.FileUnlock(pfh: PFileHandle; pos, size: integer);
begin
   if (pfh = nil) or (pfh.inUse <> True) or pfh.pfe.Deleted then
      raise EMMFastFileError.Create(LoadResStr(IDS_FFBADHANDLE));

   if (size > 0) then
      if (pos+size) > PFileEntry(PChar(pfh.pfe)+sizeOf(pfh.pfe^)).Offset then
         raise EMMFastFileError.Create(LoadResStr(IDS_FFFILEEND));
end;

{-- TMMFastFile ---------------------------------------------------------}
function TMMFastFile.FileRead(pfh: PFileHandle; Buffer: PChar; size: integer): integer;
begin
   Result := 0;
   if (pfh = nil) or (pfh.inUse <> True) or pfh.pfe.Deleted then
      raise EMMFastFileError.Create(LoadResStr(IDS_FFBADHANDLE));

   size := Min(size,PFileEntry(PChar(pfh.pfe)+sizeOf(pfh.pfe^)).Offset - pfh.pos);

   if (size > 0) then
   begin
      move((FPBase + pfh.pos)^, Buffer^, size);
      inc(pfh.pos,size);
      Result := size;
   end;
end;

{-- TMMFastFile ---------------------------------------------------------}
function TMMFastFile.FileSeek(pfh: PFileHandle; pos, origin: integer): integer;
var
   pfe: PFileEntry;

begin
   Result := -1;
   if (pfh = nil) or (pfh.inUse <> True) or pfh.pfe.Deleted then
      raise EMMFastFileError.Create(LoadResStr(IDS_FFBADHANDLE));

   pfe := pfh.pfe;
   if (origin = SEEK_SET) then
   begin
      if (pos < 0) or (pos >= pfh.size) then
         raise EMMFastFileError.Create(LoadResStr(IDS_FFBADOFFSET));

      inc(pos,pfe.offset);
   end
   else if (origin = SEEK_END) then
   begin
      if (pos < 0) or (pos >= pfh.size) then
         raise EMMFastFileError.Create(LoadResStr(IDS_FFBADOFFSET));

      pos := PFileEntry(PChar(pfe)+sizeOf(pfe^)).offset - pos;
   end
   else if (origin = SEEK_CUR) then
   begin
      pos := pfh.pos + pos;
      if (pos < pfe.offset) or (pos >= PFileEntry(PChar(pfe)+sizeOf(pfe^)).offset) then
         raise EMMFastFileError.Create(LoadResStr(IDS_FFBADOFFSET));
   end
   else raise EMMFastFileError.Create(LoadResStr(IDS_FFBADORIGIN));

   pfh.pos := pos;
   Result := pos - pfe.offset;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -