zoukankan      html  css  js  c++  java
  • delphi内存映射 与 映射数据获取


     

     

    一.原理

        通过使用“内存映射文件”,实现内存共享

    二.主要操作

        共享内存结构:

    复制代码
      PShareMem = ^TShareMem;
      TShareMem = Record
        id:string[10];
        name:string[20];
        age:Integer;
      end;

    // 一定要注意 固定长度
    复制代码

        基本变量:

        shareMemName:string; //共享内存名
        fileHandle : THandle;//内存映射文件句柄
        pUserInfoShareMem : PShareMem;//指向共享内存的指针

        a)写入程序

            1)创建“内存映射文件”

    复制代码
    begin
       //创建“内存映射文件”
       fileHandle:=CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TShareMem), PChar(shareMemName));
    if fileHandle <> 0 then begin Self.Memo1.Lines.Add('已成功创建内存映射文件!'); end; end;
    复制代码

            2)建立映射关系

    复制代码
      //将“内存映射文件”与“应用程序地址空间”建立映射关系
      pUserInfoShareMem:=MapViewOfFile(fileHandle,FILE_MAP_ALL_ACCESS,0,0,sizeof(TShareMem));
      if pUserInfoShareMem <> nil then
      begin
         Self.Memo1.Lines.Add('已成功建立映射关系!');
      end;
    复制代码

            3)写入信息

       pUserInfoShareMem.id:='8888';
       pUserInfoShareMem.name:='Terry';
       pUserInfoShareMem.age:=25;
       Self.Memo1.Lines.Add('已向共享内存中写入用户信息!');

            4)解除映射关系

      //解除“内存映射文件”与“应用程序地址空间”的映射关系
      if pUserInfoShareMem<> nil then
         UnmapViewOfFile(pUserInfoShareMem);
      Self.Memo1.Lines.Add('已成功解除映射关系!');

            5)关闭“内存映射文件”

      //关闭内存映射文件
      if fileHandle<> 0 then
         CloseHandle(fileHandle);
      Self.Memo1.Lines.Add('已成功关闭内存映射文件!');

     

        b)读取程序

            1)打开“内存映射文件”

     fileHandle:=OpenFileMapping(FILE_MAP_ALL_ACCESS,false,pchar(shareMemName));
      if self.FileHandle <> 0 then
      begin
        Self.Memo1.Lines.Add('已成功打开内存映射文件!')
      end;

            2)建立映射关系

    复制代码
       pUserInfoShareMem:= MapViewOfFile(self.FileHandle,windows.FILE_MAP_ALL_ACCESS,0,0,sizeof(TShareMem));
       if pUserInfoShareMem <> nil then
       begin
         Self.Memo1.Lines.Add('已成功建立映射关系!');
       end;
    复制代码

            3)读取信息

    复制代码
       if pUserInfoShareMem <> nil then
       begin
          userInfoStr:='共享内存中获取的用户信息如下:'+#13#10;
          userInfoStr:=userInfoStr+'用户Id号:'+pUserInfoShareMem.id+#13#10;
          userInfoStr:=userInfoStr+'用户姓名:'+pUserInfoShareMem.name+#13#10;
          userInfoStr:=userInfoStr+'用户年龄:'+IntToStr(pUserInfoShareMem.age);
          Self.Memo1.Lines.Add(userInfoStr);
       end; 
    复制代码

            4)解除映射关系

      if pUserInfoShareMem<> nil then
         UnmapViewOfFile(pUserInfoShareMem);
      Self.Memo1.Lines.Add('已成功解除映射关系!');

            5)关闭“内存映射文件”

      if fileHandle<> 0 then
         CloseHandle(fileHandle);
      Self.Memo1.Lines.Add('已成功关闭内存映射文件!');

    ====================================================

    以下 转自 http://blog.csdn.net/bdmh/article/details/6369250
     

    procedure TGetDataThread.DoGetData;
    var
      FFile_Handle: THandle;
      FFile_Map: THandle;
      list: TStringList;
      p: PChar;
      i, interval: Integer;
    
    begin
      try
        totallen := 0;
        offset := 0;
        tstream := TMemoryStream.Create;
        stream := TMemoryStream.Create;
        list := TStringList.Create;
        // 获取系统信息
        GetSystemInfo(sysinfo);
        // 页面分配粒度大小
        blocksize := sysinfo.dwAllocationGranularity;
        // 打开文件
        FFile_Handle := CreateFile(PChar(FSourceFileName), GENERIC_READ,
          FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
        if FFile_Handle = INVALID_HANDLE_VALUE then
          Exit;
        // 获取文件尺寸
        filesize := GetFileSize(FFile_Handle, nil);
        // 创建映射
        FFile_Map := CreateFileMapping(FFile_Handle, nil, PAGE_READONLY, 0, 0, nil);
        if FFile_Map = 0 then
          Exit;
        // 此处我们已10倍blocksize为一个数据块来映射,如果文件尺寸小于10倍blocksize,则直接映射整个文件长度
        if filesize div blocksize > 10 then
          readlen := 10 * blocksize
        else
          readlen := filesize;
        for i := 0 to FInfoList.Count - 1 do
        begin
          list.Delimiter := ':';
          list.DelimitedText := FInfoList.Strings[i];
          // 取得长度,我这里做了解析,因为我存储的信息为 a:b:c 这种类型,所以以:号分隔
          len := StrToInt(list.Strings[1]);
          interval := StrToInt(list.Strings[2]);
          if (i = 0) or (totallen + len >= readlen) then
          begin
            // 如果已读取的长度加上即将要读取的长度大于 10倍blocksize,那么我们要保留之前映射末尾的内容,以便和新映射的内容合并
            if i > 0 then
            begin
              offset := offset + readlen;
              // 写入临时流
              tstream.Write(p^, readlen - totallen);
              tstream.Position := 0;
            end;
            // 如果未读取的数据长度已经不够一个分配粒度,那么就直接映射剩下的长度
            if filesize - offset < blocksize then
              readlen := filesize - offset;
            // 映射,p是指向映射区域的指针
            // 注意这里第三个参数,一直设为0,这个值要根据实际情况设置
            p := PChar(MapViewOfFile(FFile_Map, FILE_MAP_READ, 0, offset, readlen));
          end;
          // 如果临时流中有数据,需要合并
          if tstream.Size > 0 then
          begin
            // 把临时流数据copy过来
            stream.CopyFrom(tstream, tstream.Size);
            // 然后在末尾写入新数据,合并完成
            stream.Write(p^, len - tstream.Size);
            totallen := len - tstream.Size;
            // 移动指针的位置,指向下一个数据的开始
            Inc(p, len - tstream.Size);
            tstream.Clear;
          end
          else
          begin
            stream.Write(p^, len);
            totallen := totallen + len;
            Inc(p, len);
          end;
          stream.Position := 0;
          // 将流保存成文件
          stream.SaveToFile(IntToStr(i) + '.txt');
          stream.Clear;
        end;
      finally
        stream.Free;
        tstream.Free;
        CloseHandle(FFile_Handle);
        CloseHandle(FFile_Map);
      end;
    end;
  • 相关阅读:
    【shell】两种字符串提取场景的实现
    【batch】批处理文件多参数处理和for循环字符串连接
    【Java】「深入理解Java虚拟机」学习笔记(4)- 类文件结构
    【Java】「深入理解Java虚拟机」学习笔记(2)- JVM内存区域
    【Java】「深入理解Java虚拟机」学习笔记(1)
    【Myeclipse】用Myeclipse10.5搭建C/C++开发环境
    【JDK】JDK模块化(1)-为什么要模块化
    【DOS】文件统计命令
    【java】转:Windows系统下面多个jdk版本切换
    【Web】servlet、filter和listener
  • 原文地址:https://www.cnblogs.com/key-ok/p/3380793.html
Copyright © 2011-2022 走看看