📄 mmffile.pas
字号:
begin
if (FPFileEntries = nil) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFNOTINIT));
if (index < Count) then
begin
j := 0;
for i := 0 to FPFileEntryCount^-1 do
begin
fe := FPFileEntries[i];
if not fe.Deleted then
begin
if (j = index) then
begin
Result := fe.Name;
exit;
end;
inc(j);
end;
end;
end;
Result := '';
raise EMMFastFileError.Create(LoadResStr(IDS_FFBADINDEX));
end;
{-- TMMFastFile ---------------------------------------------------------}
function TMMFastFile.GetFilesByName(Name: string): string;
var
fe: TFileEntry;
pfe: PFileEntry;
begin
if (FPFileEntries = nil) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFNOTINIT));
if (Name <> '') then
begin
fe.Name := PChar(Name);
pfe := lfind(@fe, FPFileEntries, FPFileEntryCount^, sizeof(TFileEntry), @Compare);
if (pfe <> nil) then
begin
Result := pfe.Name;
end;
end
else
begin
Result := '';
raise EMMFastFileError.Create(LoadResStr(IDS_FFBADFILENAME));
end;
end;
{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.CreateFastFile(FileName: TFileName; nMaxFiles: integer);
var
hOut: integer;
pfe: PFileEntryArray;
Tmp: Longint;
begin
if FileName = '' then exit;
hOut := FileCreate(FileName);
if (hOut < 0) then
raise EMMFastFileError.CreateFmt(LoadResStr(IDS_FFCREATEERROR),['FastFile']);
try
inc(nMaxFiles); // make place for one entry more
pfe := nil;
pfe := GlobalAllocMem(nMaxFiles * sizeOf(TFileEntry));
FillChar(pfe^, nMaxFiles * sizeOf(TFileEntry), 0);
FileName := ExpandUNCFileName(FileName);
if FileWrite(hOut, KENNUNG, sizeOf(KENNUNG)-1) <> sizeOf(KENNUNG)-1 then
raise EMMFastFileError.Create(LoadResStr(IDS_FFWRITEERROR));
// write the number of max directory entries
Tmp := nMaxFiles-1;
if FileWrite(hOut, Tmp, sizeOf(Tmp)) <> sizeOf(Tmp) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFWRITEERROR));
// write the number of current directory entries (0)
Tmp := 0;
if FileWrite(hOut, Tmp, sizeOf(Tmp)) <> sizeOf(Tmp) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFWRITEERROR));
{$IFDEF TRIAL}
{$DEFINE _HACK1}
{$I MMHACK.INC}
{$ENDIF}
// set the offset for the first entry
pfe[0].Offset := (sizeOf(KENNUNG)-1+2*sizeOf(Longint)) + nMaxFiles * sizeOF(TFileEntry);
if FileWrite(hOut, pfe^, nMaxFiles * sizeOf(TFileEntry)) <> nMaxFiles * sizeOf(TFileEntry) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFWRITEERROR));
finally
SysUtils.FileClose(hOut);
GlobalFreeMem(Pointer(pfe));
end;
end;
{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.Init;
begin
if (FFileName = '') or not SysUtils.FileExists(FFileName) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFBADFILENAME));
// make sure any old FastFile is closed
Done;
try
// get a file handle array
ReAllocMem(FPFileHandles, FMaxHandles*SizeOf(TFileHandle));
if (FPFileHandles = nil) then OutOfMemoryError;
FillChar(FPFileHandles^, FMaxHandles * sizeOf(TFileHandle), 0);
// create a memory mapped file for the master file
FHFile := CreateFile(PChar(FFileName), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0);
if (FHFile = 0) or (FHFile = HFILE_ERROR) then
begin
FHFile := 0;
raise EMMFastFileError.Create('CreateFile failed with Error Code: '+IntToStr(GetLastError));
end;
FHFileMapping := CreateFileMapping(FHFile,nil,PAGE_READWRITE,0,0,nil);
if (FHFileMapping = 0) then
raise EMMFastFileError.Create('CreateFileMapping failed with Error Code: '+IntToStr(GetLastError));
FPBase := MapViewOfFile(FHFileMapping, FILE_MAP_WRITE, 0, 0, 0);
if (FPBase = nil) then
raise EMMFastFileError.Create('MapViewOfFile failed with Error Code: '+IntToStr(GetLastError));
// get initial data from the memory mapped file
FMaxFiles := PLongint(FPBase+sizeOf(KENNUNG)-1)^;
FPFileEntryCount := PLongint(FPBase + sizeOf(KENNUNG)-1 + sizeOf(Longint));
FPFileEntries := PFileEntryArray(FPBase + sizeOf(KENNUNG)-1 + 2*sizeOf(Longint));
except
Done;
raise;
end;
end;
{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.UpdateFastFile(Size: integer);
begin
try
if (FHFileMapping <> 0) then
begin
if (FPBase <> nil) then
begin
UnmapViewOfFile(FPBase);
FPBase := nil;
end;
CloseHandle(FHFileMapping);
FHFileMapping := 0;
end;
if (FHFile <> 0) then
FHFileMapping := CreateFileMapping(FHFile,nil,PAGE_READWRITE,0,Size,nil);
if (FHFileMapping = 0) then
raise EMMFastFileError.Create('CreateFileMapping failed with Error Code: '+IntToStr(GetLastError));
FPBase := MapViewOfFile(FHFileMapping, FILE_MAP_WRITE, 0, 0, 0);
if (FPBase = nil) then
raise EMMFastFileError.Create('MapViewOfFile failed with Error Code: '+IntToStr(GetLastError));
// get initial data from the memory mapped file
FMaxFiles := PLongint(FPBase+sizeOf(KENNUNG)-1)^;
FPFileEntryCount := PLongint(FPBase + sizeOf(KENNUNG)-1 + sizeOf(Longint));
FPFileEntries := PFileEntryArray(FPBase + sizeOf(KENNUNG)-1 + 2*sizeOf(Longint));
{$IFDEF TRIAL}
{$DEFINE _HACK2}
{$I MMHACK.INC}
{$ENDIF}
HandlesLost;
except
Done;
raise;
end;
end;
{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.Done;
begin
Pack;
if (FHFileMapping <> 0) then
begin
if (FPBase <> nil) then UnmapViewOfFile(FPBase);
CloseHandle(FHFileMapping);
FHFileMapping := 0;
end;
if (FHFile <> 0) then
begin
CloseHandle(FHFile);
FHFile := 0;
end;
if (FPFileHandles <> nil) then
begin
ReAllocmem(FPFileHandles,0);
FPFileHandles := nil;
end;
FPBase := nil;
FPFileEntryCount := nil;
FPFileEntries := nil;
end;
{-- TMMFastFile ---------------------------------------------------------}
function TMMFastFile.AddFile(const Name: TFileName): TFileName;
var
hIn : THandle;
Bytes,pos: integer;
Buffer : PChar;
NewName : String;
begin
Result := '';
if (FPFileEntries = nil) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFNOTINIT));
hIn := 0;
Buffer := nil;
try
// is place for more entry's ?
if (FPFileEntryCount^ >= FMaxFiles) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFDIRFULL));
// get a short filename for the new file
NewName := GetShortFileName(Name);
if (NewName = '') then
raise EMMFastFileError.Create(LoadResStr(IDS_FFBADFILENAME));
// is the file already in directory or deleted ?
if FileExists(NewName) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFDUPLICATEFILENAME));
// open the new file
hIn := SysUtils.FileOpen(Name, fmOpenRead);
if (hIn < 0) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFOPENERROR));
Buffer := GlobalAllocMem(BLOCK_SIZE);
// adjust the size for the MemMapFile
UpdateFastFile(FPFileEntries[FPFileEntryCount^].Offset+ GetFileSize(Name));
pos := FPFileEntries[FPFileEntryCount^].Offset;
while True do
begin
Bytes := SysUtils.FileRead(hIn, Buffer^, BLOCK_SIZE);
if (Bytes = 0) then break;
if (Bytes < 0) then
raise EMMFastFileError.Create(LoadResStr(IDS_FFREADERROR));
try
move(Buffer^, (FPBase + pos)^, Bytes);
inc(pos, Bytes);
except
raise EMMFastFileError.Create(LoadResStr(IDS_FFWRITEERROR));
end;
if (Bytes < BLOCK_SIZE) then break;
end;
FPFileEntries[FPFileEntryCount^].Name := NewName;
FPFileEntries[FPFileEntryCount^].Deleted := False;
FPFileEntries[FPFileEntryCount^].Size := pos - FPFileEntries[FPFileEntryCount^].Offset;
// inc the directory entry counter
inc(FPFileEntryCount^);
// save current file position for the next entry
FPFileEntries[FPFileEntryCount^].Offset := pos;
Result := NewName;
Change;
finally
SysUtils.FileClose(hIn);
GlobalFreeMem(Pointer(Buffer));
end;
end;
{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.RemoveFile(const Name: TFileName);
var
fe : TFileEntry;
pfe: PFileEntry;
i : integer;
begin
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 (FPFileHandles[i].pfe <> nil) and
(FPFileHandles[i].pfe.Name = pfe.Name) then
begin
FPFileHandles[i].inUse := False;
break;
end;
end;
pfe.Deleted := True;
inc(FNumDeleted);
Change;
end
else raise EMMFastFileError.CreateFmt(LoadResStr(IDS_FFNOTFOUND),[Name]);
end;
{-- TMMFastFile ---------------------------------------------------------}
procedure TMMFastFile.RenameFile(const OldName, NewName: TFileName);
var
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -