能否把内存流或磁盘上的某个文件的一部分映射为磁盘上的一个文件,供其它程序调用?

flyinwuhan 2004-03-17 04:43:52
假设我把一片Memory或者一个文件的一部分映射为"c:\test.txt"
然后另一个进程直接读"c:\test.txt"的内容呢?
注意仅仅是映射而不是写入"c:\test.txt"

不想用IPC共享内存,我的思路是否可行?请指点。
...全文
52 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
stanely 2004-03-19
  • 打赏
  • 举报
回复
内存映像的特点似乎不适合封装成流,尤其是setsize的时候有些牵强,还有就是不好得到已经创建的映像的信息。也可能是鄙人驽钝,不知道ms提供这样的方法。

哪位知道请赐教!
stanely 2004-03-19
  • 打赏
  • 举报
回复
我不知道怎样得到已经存在的内存映象的信息比如他的大小等。。。

不然这个类就完善了。

你可以用来代替原来的stream,或者用它来映射文件,只要在create里面设置handle是你打开的文件的handle就可以,打开文件的时候一定要注意保护模式不要和创建参数有冲突。

当时设计的用handle而不是直接一个文件名,些两个overload的constructor就好了,一个专门用于内存,一个专门用于文件。其实就是多了个openfile调用而已,对于内存映射就是handle传入$ffffffff,懒得封装了。

希望对你有用。
stanely 2004-03-19
  • 打赏
  • 举报
回复
unit FileMapStream_san;

interface
uses
windows,classes,sysutils;

const
c_memhandle=$FFFFFFFF;
c_msg_cannotsetsize='Cannot set the size of a "%s" object, except for setting the "%s" property to True.';

type


TProtection_san=(pREAD,pREADWRITE,pCOPY);
TAdditionalProtection_san=(apCOMMIT,apIMAGE,apNOCACHE,apRESERVE);
TAdditionalProtections_San=set of tadditionalprotection_san;
TFileMapStream_San=class(TStream)
private
FFileHandle:cardinal;
FMapHandle:cardinal;
FStartPointer:pointer;
FCurrentPointer:pointer;
FMapName:string;
FSize:cardinal;
FProtection:TProtection_San;
fAdditionalProtections:TAdditionalProtections_san;
FAlreadyExists:boolean;
//////////
FInitializing:boolean;
protected
procedure SetSize(NewSize: Longint); overload; override;
function StartPointer():pointer;
function CurrentPointer():pointer;
public
AutoSize:boolean;
////////////////////
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;

constructor Create(const AMapName:string='';ASize: cardinal=0;AHandle: cardinal=c_memhandle;
AProtection:TProtection_San=pREADWRITE;AAdditionalProtections:TAdditionalProtections_San=[]);
destructor Destroy;override;

class function FileMapExists(AMapName:string):boolean;
function ToString:string;

published
property FileHandle:cardinal read ffilehandle;
property MapHandle:cardinal read fmaphandle;
property MapName:string read fmapname;
property Protection:tprotection_san read fprotection;
property AdditionalProtection:Tadditionalprotections_san read fadditionalprotections;
property AlreadyExists:boolean read falreadyexists;
end;

implementation

{ TFileMapStream_San }

constructor TFileMapStream_San.create(const AMapName:string;ASize: cardinal;AHandle: cardinal;
AProtection:TProtection_San;AAdditionalProtections:TAdditionalProtections_San);
var
n:pchar;
p,p1:cardinal;
begin
FInitializing:=true;

ffilehandle:=ahandle;
fmapname:=amapname;

fprotection:=aprotection;
fadditionalprotections:=aadditionalprotections;
autosize:=asize<=0;
self.setsize(asize);

end;

procedure TFileMapStream_San.SetSize(NewSize: Integer);
var
n:pchar;
p1,p:cardinal;
begin
if (not autosize)and(not FInitializing) then
raise exception.Create(format(c_msg_cannotsetsize,[classname,'AutoSize']));
if newsize<0 then newsize:=0;
if (newsize=size) and (newsize<>0) then exit;

fsize:=newsize;
unmapviewoffile(fstartpointer);
closehandle(fmaphandle);

if fmapname='' then
n:=nil
else
n:=pchar(fmapname);

p:=0;
p1:=0;

if fprotection=pread then
begin
p:=page_readonly;
p1:=FILE_MAP_READ;

end;
if preadwrite = fprotection then
begin
p:=page_readwrite;
p1:= FILE_MAP_WRITE ;
end;
if pcopy = fprotection then
begin
p:= page_writecopy;
p1:= FILE_MAP_COPY;
end;
if apCommit in fadditionalprotections then p:=p or sec_commit;
if apImage in fadditionalprotections then p:=p or sec_image;
if apNocache in fadditionalprotections then p:=p or sec_nocache;
if apReserve in fadditionalprotections then p:=p or sec_reserve;

fmaphandle:=createfilemapping(ffilehandle,nil,p,0,fsize,n);

if (fmaphandle=0) then
begin
RaiseLastOSError;
end else
begin
self.FAlreadyExists:=getlasterror=ERROR_ALREADY_EXISTS;

FstartPointer:=mapviewoffile(fmaphandle,p1,0,0,0);
if fstartpointer=nil then RaiseLastOSError;

fcurrentpointer:=fstartpointer;
end;
FInitializing:=false;
end;

destructor TFileMapStream_San.Destroy;
begin
unmapviewoffile(fstartpointer);
closehandle(fmaphandle);
//msg;
inherited;
end;

class function TFileMapStream_San.FileMapExists(AMapName: string): boolean;
var
n:pchar;
h:cardinal;
begin
if amapname='' then
n:=nil
else
n:=pchar(amapname);
h:=createfilemapping(c_memhandle,nil,page_readonly,0,1,n);
result:=(h<>0)and(getlasterror=ERROR_ALREADY_EXISTS);
closehandle(h);
end;

function TFileMapStream_San.StartPointer(): pointer;
begin
result:=fstartpointer;
end;

function TFileMapStream_San.Read(var Buffer; Count: Integer): Longint;
var
c:cardinal;
begin
c:=size-position;
if c>count then
result:=count
else
result:=c;

copymemory(@buffer,fcurrentpointer,result);
position:=position+result;
end;

function TFileMapStream_San.Write(const Buffer; Count: Integer): Longint;
var
p:pointer;
begin
p:=fcurrentpointer;
self.setsize(position+count);

fcurrentpointer:=p;
copymemory(fcurrentpointer,@buffer,count);
position:=position+count;
result:=count;
end;

function TFileMapStream_San.Seek(Offset: Integer; Origin: Word): Longint;
begin

case origin of
soFromBeginning:
begin
result:=offset;
end;
soFromEnd:
begin
result:=fsize+offset;
end;
soFromCurrent:
begin
result:=cardinal(fcurrentpointer)-cardinal(fstartpointer)+offset;
end;
end;
fcurrentpointer:=pointer(cardinal(fstartpointer)+result);
if result<0 then
result:=0
else if result>fsize then result:=fsize;

end;


function TFileMapStream_San.CurrentPointer(): pointer;
begin
result:=fcurrentpointer;
end;

function TFileMapStream_San.ToString: string;
begin
setlength(result,size);
copymemory(@result[1],fstartpointer,size);
end;

end.
flyinwuhan 2004-03-19
  • 打赏
  • 举报
回复
Thanks to stanely(俺是邢她汉子) !
killdata 2004-03-19
  • 打赏
  • 举报
回复
好奇怪啊,只是一个内存数据公用就这么麻烦,你丢到剪切板上不就行了。

或者直接让第二个程序使用第一个程序的函数(dll)即可啊.
pandengzhe 2004-03-18
  • 打赏
  • 举报
回复
内存映射
koma2003 2004-03-18
  • 打赏
  • 举报
回复
用内存映射文件可以实现
flyinwuhan 2004-03-18
  • 打赏
  • 举报
回复
呵呵,我再UP,期待高手出现中。。。。。。。。。
nnfish 2004-03-18
  • 打赏
  • 举报
回复
学习,,
stanely 2004-03-18
  • 打赏
  • 举报
回复
映射可以,但是windows无法和delphi的stream通信,想把stream映射成其他进程可以访问的共享资源是不可能的。只能把你的stream的东西拷贝到另外建立好的映射文件中再跟其他进程共享。

对于文件和文件的一部分是可以的,但是不需要映射成另外一个文件。因为访问映射内容的时候都是依靠一个指针。

我写了个映射文件的Stream类,可能有点牵强,但是我想能避免你用流的时候额外拷贝到英社区的操作,因为你可以直接用“内存映射流类”的实例代替原来的任何流类。

晚上给你贴出来。
flyinwuhan 2004-03-18
  • 打赏
  • 举报
回复
麻烦楼上两位给个简单的例子。。。。。。
嫌分少的话再加!
flyinwuhan 2004-03-17
  • 打赏
  • 举报
回复
吧!
cll007 2004-03-17
  • 打赏
  • 举报
回复
学习 一下下
aiirii 2004-03-17
  • 打赏
  • 举报
回复
我也不會, 參與!!
zyxg 2004-03-17
  • 打赏
  • 举报
回复
老大,我不会就帮你顶吧!

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧