知道Name么?知道的话就简单了。这段拷给你。
unit MemMappedFiles;
interface
uses Windows, Classes;
type
TAccessMode = (amReadOnly, amReadWrite);
TMemMappedFile = class
private
FName: string;
FFileName: string;
FAccessMode: TAccessMode;
FSize: Integer;
FHandle: THandle;
function GetHandle: THandle;
public
constructor Create(const AName: string; AMode: TAccessMode; ASize: Integer;
const AFileName: string); overload;
constructor Create(const AName: string; AMode: TAccessMode; ASize: Integer); overload;
destructor Destroy; override;
function CreateMapView(AMode: TAccessMode): TStream;
end;
implementation
uses SysUtils, Logs;
type
EWindowsError = class(Exception)
public
constructor Create;
end;
TMapViewStream = class(TStream)
private
FMemMappedFile: TMemMappedFile;
FCanWrite: Boolean;
FAddress: Pointer;
FPosition: Integer;
FMutexName: array[0..MAX_PATH] of Char;
FMutex: THandle;
procedure EnsureCreated;
public
constructor Create(AMemMappedFile: TMemMappedFile; AMode: TAccessMode);
destructor Destroy; override;
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; overload; override;
end;
{ EFileMapException }
function GetLastErrorMessage: string;
var
Buf: array[0..1023] of char;
Len: Integer;
begin
Len := FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,
nil, GetLastError, 0, Buf, 1024, nil);
SetString(Result, Buf, Len);
end;
constructor EWindowsError.Create;
begin
inherited Create(GetLastErrorMessage);
end;
{ TMapViewStream }
constructor TMapViewStream.Create(AMemMappedFile: TMemMappedFile;
AMode: TAccessMode);
begin
FMemMappedFile := AMemMappedFile;
FCanWrite := AMode = amReadWrite;
FAddress := nil;
FPosition := 0;
if FCanWrite then
begin
StrPLCopy(FMutexName, Format('MUTEX_%s', [FMemMappedFile.FName]), MAX_PATH);
FMutex := CreateMutex(nil, True, FMutexName);
if FMutex = 0 then
begin
FMutex := OpenMutex(MUTEX_ALL_ACCESS or Windows.SYNCHRONIZE, False,
FMutexName);
if WaitForSingleObject(FMutex, 0) <> WAIT_OBJECT_0 then
begin
CloseHandle(FMutex);
FMutex := 0;
FCanWrite := False;
end;
end;
end;
end;
destructor TMapViewStream.Destroy;
begin
if FMutex <> 0 then
begin
ReleaseMutex(FMutex);
CloseHandle(FMutex);
end;
if FAddress <> nil then
begin
FlushViewOfFile(FAddress, FMemMappedFile.FSize);
UnmapViewOfFile(FAddress);
end;
inherited;
end;
procedure TMapViewStream.EnsureCreated;
const
Accesses: array[Boolean] of Cardinal = (FILE_MAP_READ, FILE_MAP_WRITE);
begin
if FAddress = nil then
begin
FAddress := MapViewOfFile(FMemMappedFile.GetHandle, Accesses[FCanWrite],
0, 0, FMemMappedFile.FSize);
if FAddress = nil then
raise EWindowsError.Create;
end;
end;
function TMapViewStream.Read(var Buffer; Count: Integer): Longint;
begin
EnsureCreated;
if (FPosition >= 0) and (Count >= 0) then
begin
Result := FMemMappedFile.FSize - FPosition;
if Result > 0 then
begin
if Result > Count then Result := Count;
Move(Pointer(Longint(FAddress) + FPosition)^, Buffer, Result);
Inc(FPosition, Result);
Log.Write(Format('读出 %d 字节', [Result]));
Exit;
end;
end;
Result := 0;
end;
function TMapViewStream.Seek(Offset: Integer; Origin: Word): Longint;
begin
EnsureCreated;
case Origin of
soFromBeginning: FPosition := Offset;
soFromCurrent: Inc(FPosition, Offset);
soFromEnd: FPosition := FMemMappedFile.FSize + Offset;
end;
Result := FPosition;
end;
function TMapViewStream.Write(const Buffer; Count: Integer): Longint;
begin
if not FCanWrite then
raise Exception.Create('该映射视图不能写入任何内容')
else
if (FPosition >= 0) and (Count >= 0) then
begin
EnsureCreated;
Result := FMemMappedFile.FSize - FPosition;
if Result > 0 then
begin
if Result > Count then Result := Count;
System.Move(Buffer, Pointer(Longint(FAddress) + FPosition)^, Result);
Inc(FPosition, Result);
Log.Write(Format('写入 %d 字节', [Result]));
Exit;
end;
end;
Result := 0;
end;
{ TMemMappedFile }
constructor TMemMappedFile.Create(const AName: string; AMode: TAccessMode;
ASize: Integer; const AFileName: string);
begin
FName := AName;
FFileName := AFileName;
FAccessMode := AMode;
FSize := ASize;
end;
constructor TMemMappedFile.Create(const AName: string; AMode: TAccessMode;
ASize: Integer);
begin
Create(AName, AMode, ASize, '');
end;
function TMemMappedFile.CreateMapView(AMode: TAccessMode): TStream;
begin
if FAccessMode = amReadOnly then
AMode := amReadOnly;
Result := TMapViewStream.Create(Self, AMode);
end;
destructor TMemMappedFile.Destroy;
begin
if FHandle <> 0 then
CloseHandle(FHandle);
inherited;
end;
function TMemMappedFile.GetHandle: THandle;
const
DesiredAccesses: array[TAccessMode] of Cardinal = (GENERIC_READ, GENERIC_WRITE);
Protections: array[TAccessMode] of Cardinal = (PAGE_READONLY, PAGE_READWRITE);
var
FileHandle: THandle;
begin
if FHandle = 0 then
begin
if Length(FFileName) > 0 then
begin
FileHandle := CreateFile(PChar(FFileName), DesiredAccesses[FAccessMode],
0, nil, OPEN_ALWAYS, 0, 0);
if FileHandle = INVALID_HANDLE_VALUE then
raise EWindowsError.Create;
end
else
FileHandle := INVALID_HANDLE_VALUE;
FHandle := CreateFileMapping(FileHandle, nil, Protections[FAccessMode],
0, FSize, PChar(FName));
if FileHandle <> INVALID_HANDLE_VALUE then
CloseHandle(FileHandle);
if FHandle = 0 then
raise EWindowsError.Create;
end;
Result := FHandle;
end;
end.
创建一个TMemMappedFile实例后,再用CreateMapView建立一个流,访问这个流即可。