首页  编辑  

内存映射文件流

Tags: /超级猛料/Stream.File.流、文件和目录/流操作/   Date Created:

内存映射文件流

...implements a Data-sharing Stream Between Applications?

Author: sanease  

Homepage: http://www.sanease.com

0 Comments to this tip [Write new comment]

[ Print tip ]    

Tip Rating (0):  

     

{

This unit implement a Stream class supporting the FileMapping utilities.

The class TFileMappingStream_San inherits TStream, and provide with an

easier way to manipulate the FileMapping objects in comparison of windows APIs.

It's a pity that there is not ,in my opinion , a way to detect the size

of a FileMapping Object with a specific name,which was already created

directly by windows API or others. Anyone knows ,please tell me.

Thanks! sanease@tom.com

}

unit FileMapping_San;

interface

uses

 windows, messages, sysutils, classes;

const

 c_msgstr = 'msgstr_san_{9BB1155F-1A06-4664-AB21-AB0A0C05A658}';

 c_emsamename = 'The global atom with the name of "%s" already exists';

 c_emdiskfull = 'The disk is full , it''s unable to Create the filemapping' +

                'with the Size of %d bytes and the Name of "%s"';

 c_emunknown = 'Unknown error occured when create file mapping with the name of "%s"';

 c_emprotect = 'The protect mode %d of filemapping is invalid with the name of "%s"';

type

 TFileMappingStream_San = class(TStream)

 private

   FMapHandle: DWORD;

   FFileHandle: DWORD;

   FName: PChar;

   FExists: Boolean;

   FPointer: Pointer;

   FProtectMode: DWORD;

   FSize: DWORD;

   FResizeable: Boolean;

   FPosition: DWORD;

   /////////

   function getname: string;

 public

   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;

   function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; override;

   function AlreadyExists: Boolean;

   function DataPointer: Pointer;

   ///////////////////////////

   constructor Create; overload;

   constructor Create(AHandle: DWORD; AName: string; ASize: Cardinal); overload;

   constructor Create(AHandle: DWORD; ASize: Cardinal); overload;

   constructor CreateFromMemory(AName: string; ASize: Cardinal); overload;

   constructor CreateFromMemory(ASize: Cardinal); overload;

   constructor Create(AHandle: DWORD; AName: string; ASize: Cardinal;

     ProtectMode: DWORD);

     overload;

   constructor Create(AHandle: DWORD; ASize: Cardinal; ProtectMode: DWORD); overload;

   constructor CreateFromMemory(AName: string; ASize: Cardinal; ProtectMode: DWORD);

     overload;

   constructor CreateFromMemory(ASize: Cardinal; ProtectMode: Integer); overload;

   destructor Destroy; override;

 published

   property MapHandle: DWORD read fmaphandle;

   property FileHandle: DWORD read ffilehandle;

   property Name: string read getname;

   property ProtectMode: DWORD read fprotectmode;

 end;

implementation

{ TFileMapping_San }

constructor TFileMappingStream_San.Create(AHandle: DWORD; AName: string;

 ASize: Cardinal);

begin

 Create(ahandle, aname, asize, PAGE_READWRITE);

end;

constructor TFileMappingStream_San.Create(AHandle: DWORD; AName: string;

 ASize: Cardinal; ProtectMode: DWORD);

var

 i: DWORD;

begin

 if asize < 0 then asize := 0;

 fresizeable := asize = 0;

 fmaphandle  := createfilemapping(ahandle, nil, protectmode, 0,asize, PChar(aname));

 if fmaphandle = 0 then

 begin

   i := GetLastError;

   case i of

     ERROR_DISK_FULL:

       begin

         raise Exception.Create(Format(c_emdiskfull, [fname]));

       end;

     ERROR_INVALID_HANDLE:

       begin

         raise Exception.Create(Format(c_emsamename, [fname]));

       end;

     0:;

     else

       begin

         raise Exception.Create(Format(c_emprotect, [protectmode, aname]));

       end;

   end;

 end

 else

 begin

   fname := nil;

   ffilehandle := ahandle;

   fprotectmode := protectmode;

   fsize := asize;

   fexists := GetLastError = ERROR_ALREADY_EXISTS;

   i := $FFFFFFFF;

   if protectmode and PAGE_READONLY = PAGE_READONLY then

     i := i and FILE_MAP_READ;

   if protectmode and PAGE_READWRITE = PAGE_READWRITE then

     i := i and FILE_MAP_ALL_ACCESS;

   if protectmode and PAGE_WRITECOPY = PAGE_WRITECOPY then

     i := i and FILE_MAP_COPY;

   fpointer := mapviewoffile(fmaphandle, i, 0,0,0);

 end;

end;

constructor TFileMappingStream_San.Create(AHandle: DWORD; ASize: Cardinal;

 ProtectMode: DWORD);

var

 i: DWORD;

begin

 if asize < 0 then asize := 0;

 fresizeable := asize = 0;

 fmaphandle  := createfilemapping(ahandle, nil, protectmode, 0,asize, nil);

 if fmaphandle = 0 then

 begin

   i := GetLastError;

   case i of

     ERROR_DISK_FULL:

       begin

         raise Exception.Create(Format(c_emdiskfull, [asize, '']));

       end;

     ERROR_INVALID_HANDLE:

       begin

         raise Exception.Create(Format(c_emsamename, [fname]));

       end;

     0:;

     else

       begin

         raise Exception.Create(Format(c_emprotect, [protectmode, '']));

       end;

   end;

 end

 else

 begin

   fname := nil;

   ffilehandle := ahandle;

   fprotectmode := protectmode;

   fsize := asize;

   fexists := GetLastError = ERROR_ALREADY_EXISTS;

   i := $FFFFFFFF;

   if protectmode and PAGE_READONLY = PAGE_READONLY then

     i := i and FILE_MAP_READ;

   if protectmode and PAGE_READWRITE = PAGE_READWRITE then

     i := i and FILE_MAP_ALL_ACCESS;

   if protectmode and PAGE_WRITECOPY = PAGE_WRITECOPY then

     i := i and FILE_MAP_COPY;

   fpointer := mapviewoffile(fmaphandle, i, 0,0,0);

 end;

end;

function TFileMappingStream_San.AlreadyExists: Boolean;

begin

 Result := fexists;

end;

constructor TFileMappingStream_San.Create(AHandle: DWORD; ASize: Cardinal);

begin

 Create(ahandle, asize, PAGE_READWRITE);

end;

destructor TFileMappingStream_San.Destroy;

begin

 unmapviewoffile(fpointer);

 closehandle(fmaphandle);

 inherited;

end;

function TFileMappingStream_San.Seek(Offset: Integer;

 Origin: Word): Longint;

begin

 case origin of

   0:

     begin

       Result := offset;

     end;

   1:

     begin

       Result := fposition + offset;

     end;

   else

     begin

       Result := fsize + offset;

     end;

 end;

 if Result < 0 then

   Result := 0

 else if Result > fsize then

 begin

   Result := fsize;

 end;

 fposition := Result;

end;

function TFileMappingStream_San.Seek(const Offset: Int64;

 Origin: TSeekOrigin): Int64;

begin

 Result := seek(Integer(offset), Ord(origin));

end;

function TFileMappingStream_San.read(var Buffer; Count: Integer): Longint;

var

 p: Pointer;

begin

 p := Pointer(Cardinal(fpointer) + fposition);

 if (not fresizeable) and (Count > Size - fposition) then

   Count := Size - fposition;

 copymemory(@buffer, p, Count);

 Result := Count;

 Inc(fposition, Count);

end;

function TFileMappingStream_San.Write(const Buffer;

 Count: Integer): Longint;

var

 p: Pointer;

begin

 p := Pointer(Cardinal(fpointer) + fposition);

 if (not fresizeable) and (Count > Size - fposition) then

   Count := Size - fposition;

 copymemory(p, @buffer, Count);

 Result := Count;

 Inc(fposition, Count);

 if fresizeable then

   Inc(fsize, Count);

end;

constructor TFileMappingStream_San.CreateFromMemory(ASize: Cardinal);

begin

 createfrommemory(asize, PAGE_READWRITE);

end;

constructor TFileMappingStream_San.CreateFromMemory(AName: string;

 ASize: Cardinal);

begin

 createfrommemory(aname, asize, PAGE_READWRITE);

end;

constructor TFileMappingStream_San.CreateFromMemory(ASize: Cardinal;

 ProtectMode: Integer);

begin

 Create($FFFFFFFF,aSize, protectmode);

end;

constructor TFileMappingStream_San.CreateFromMemory(AName: string;

 ASize: Cardinal; ProtectMode: DWORD);

begin

 Create($FFFFFFFF,aName, asize, protectmode);

end;

function TFileMappingStream_San.DataPointer: Pointer;

begin

 Result := fpointer;

end;

function TFileMappingStream_San.getname: string;

begin

 Result := fname;

end;

constructor TFileMappingStream_San.Create;

begin

 Create(INVALID_HANDLE_VALUE, 0);

end;

end.