📄 mmffile.pas
字号:
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 + -