FH:=FileOpen(Edit2.Text,fmOpenRead); 
MH:=CreateFileMapping(FH,nil,Page_ReadOnly,0,FileSize,nil); 
CloseHandle(FH); 
MP:=MapViewOfFile(MH,File_Map_Read,0,0,FileSize);   //如果文件大于1G,这里返回的值为NIL了, 
CloseHandle(MH); 请教各位,这种要如何处理?
可以分块映射不?

解决方案 »

  1.   

    你仔细查查MapViewOfFile的参数,这个函数本来就是支持分块映射的
    顺便说一句,一次性映射太大的文件到内存是愚蠢的
      

  2.   


    supertitan002,你好,查了下MapViewOfFile函数的参数,第四个参数为要映射的字节数。用零映射整个文件映射对象 ,那如果现在分块的话是不是这么写就这么写就可以了,假设分5块:
    MP:=MapViewOfFile(MH,File_Map_Read,0,FileSize div 5,FileSize); 
      

  3.   

    这个函数没有你想象的这么简单,你应该再仔细的看看帮助
    首先你连每个参数是做什么的都没有弄清楚
    第4个参数不能随便设的,FileSize div 5更是不行的
    dwFileOffsetLowSpecifies the low-order 32 bits of the file offset where mapping is to begin. The combination of the high and low offsets must specify an offset within the file that matches the system's memory allocation granularity, or the function fails. That is, the offset must be a multiple of the allocation granularity. Use the 
    GetSystemInfo function, which fills in the members of a SYSTEM_INFO structure, to obtain the system's memory allocation granularity. 前面这段是帮助,里面讲了,这个参数必须是最小内存分块的整数倍最后一个参数是你要映射的字节,设为FileSize显然是不合适的还是仔细阅读帮助吧
      

  4.   

    嘿,非常感谢supertitan002同学的指点,回去好好研究下先:)
      

  5.   

    继续分段映射大文件问题发送端文件分段映射如下
       ///////// 大于1g文件分块传输
        FH:=FileOpen(F_MediaUpdateFile[FSendMediaCount].sPath+F_MediaUpdateFile        [FSendMediaCount].sFile,fmOpenRead);
       if (F_FileSize / (1024*1024*1024)>1) then
        begin
          //创建内存映射对象
           FSize:=GetFileSize(FH,@HighSize);
          TotalSize:=HighSize*1024*1024*1024*4+FSize;
          MH:=CreateFileMapping(FH,nil,PAGE_READONLY,HighSize,FSize,nil);
          //初始化变量
          StartPos:=0;
          MapSize:=BufferSize;
          while StartPos<TotalSize do
          begin
            if StartPos+BufferSize>TotalSize then
              MapSize:=TotalSize-StartPos;
            //创建映射视图,获得的PSource和PTarget指针,可以和操作普通指针一样进行内存操作
            PSource:=MapViewOfFile(MH,FILE_MAP_READ,High32(StartPos),Low32(StartPos),MapSize);
            I := MapSize div J;
            K:=MapSize-I*J;
            For H:=0 to J-1 do
            begin
              IF H=J-1 then
                I:=I+K;//最后的数据块
              SocketThread[H]:= TSocketThread.Create(self,H,H*I,I,PSource);
              Event[H]       := CreateEvent(nil,False,False,nil);
            end;
            StartPos:=StartPos+MapSize;
            //取消内存映射视图
            UnMapViewOfFile(PSource);
            //UnMapViewOfFile(PTarget);
          end;
          //关闭文件映射
          CloseHandle(MH);
          //CloseHandle(tMapHandle);    end;现在问题是:接收端要如何接收这种分段映射的文件呢?(远程文件传输,不是本地的)
    请教各位大虾,这种要怎么做呢?
      

  6.   

    非常感谢楼上兄弟的支持。
    以下是接收端的程序,但有问题,各位大虾帮忙看看要如何写?
    procedure TSocketProcesser.BuildFile;
    const BufferSize=1024*1024*64;
    var
      FileName:String[250];
      PS,PD:PByte;  size:DWord;
      fileType:integer;  //映射参数  FSize:Cardinal; //文件低32位大小
      HighSize:Cardinal; //文件高32位大小
      TotalSize:int64; //文件總體積
      sMapHandle:THandle; //源文件内存映射句柄
      PSource:Pointer;  //源文件内存映射视图地址
      PTarget:Pointer;  //目标文件内存映射视图地址  StartPos:Int64;
      MapSize:Cardinal;
      function MakeInt64(high,low:Cardinal):int64;
      begin
        move(pchar(@high)^,pchar(longint(@result)+sizeof(cardinal))^,sizeof(cardinal));
        move(pchar(@low)^,pchar(@result)^,sizeof(cardinal));
      end;
      function High32(num:int64):Cardinal;
      begin
        move(pchar(longint(@num)+sizeof(cardinal))^,pchar(@result)^,sizeof(cardinal));
      end;
      function Low32(num:int64):Cardinal;
      begin
        move(pchar(@num)^,pchar(@result)^,sizeof(cardinal));
      end;
    begin
      PS:=TempPointer;
      Inc(PS,32);
      PD:=@FileName;
      move(PS^,PD^,Rev.Len);
      FN:=FileName;
      //得到文件长度
      size:=Rev.F1;
      //得到总文件数
      FFileTotalCount:=Rev.F4;
      //得到文件类型
      fileType:=Rev.F5;
      //根据文件类型保存至指定目录下
      if fileType=0 then
      begin
        FH1:=FileCreate(MainForm.FDBFilePath+FileName);
        FileClose(FH1);
        FH1:=FileOpen(MainForm.FDBFilePath+FileName,fmOpenreadWrite);
      end
      else
      begin
          FH1:=FileCreate(MainForm.FMediaFilePath+FileName);
          FileClose(FH1);
          FH1:=FileOpen(MainForm.FMediaFilePath+FileName,fmOpenreadWrite);
      end;
      //文件小于1G
      if (size/(1024*1024*1024)<1) then
      begin
        FH2:=CreateFileMapping(FH1,nil,Page_ReadWrite,0,size,nil);
        CloseHandle(FH1);
        FileMapPointer:=MapViewOfFile(FH2,File_Map_All_Access,0,0,size);
      end
      else
      begin
        TotalSize:=size;
        //创建内存映射对象      //目标文件
          TargetHandle:=FileCreate(MainForm.FMediaFilePath+FileName);
          FH2:=CreateFileMapping(FH1,nil,FILE_MAP_READ,HighSize,TotalSize,nil);
          tMapHandle:=CreateFileMapping(TargetHandle,nil,PAGE_READWRITE,HighSize,TotalSize,nil);
           CloseHandle(TargetHandle);
          MainForm.mmo_Report.Lines.Add('☆开始接收文件:'+FileName+',长度'+inttostr(TotalSize div (1024*1024))+'MB,'+TimetoStr(Now()));
          //初始化变量
          StartPos:=0;
        //MapSize:=BufferSize;
        MapSize:=Rev.MD;
       { while StartPos<TotalSize do
        begin
          if StartPos+BufferSize>TotalSize then
            MapSize:=TotalSize-StartPos;  }      //创建映射视图,获得的PSource和PTarget指针,可以和操作普通指针一样进行内存操作
          FileMapPointer:=MapViewOfFile(FH2,FILE_MAP_WRITE , High32(StartPos),Low32(StartPos),MapSize);     // PSource:=MapViewOfFile(FH2,FILE_MAP_READ,High32(StartPos),Low32(StartPos),MapSize);
          PTarget:=MapViewOfFile(tMapHandle,FILE_MAP_READ or FILE_MAP_WRITE, High32(StartPos),Low32(StartPos),MapSize);
          StartPos:=StartPos+MapSize;
          //复制
          move(PByte(FileMapPointer)^,PByte(PTarget)^,MapSize);
          {//取消内存映射视图
          UnMapViewOfFile(FileMapPointer);
          UnMapViewOfFile(PTarget);  }
          inc(MainForm.FRecCount);
        {end; }
        //关闭文件映射
        //CloseHandle(MH);
        //CloseHandle(tMapHandle);
        if StartPos = TotalSize then
        begin
          //取消内存映射视图
          UnMapViewOfFile(FileMapPointer);
          UnMapViewOfFile(PTarget);
          CloseHandle(FH2);
          CloseHandle(tMapHandle);
        end;
      end;  
      FileSize:=size;//  //文件大小显示 
      if (FileSize < 1024)  then
        MainForm.mmo_Report.Lines.Add('☆开始接收文件:'+FileName+',长度'+inttostr(FileSize )+'字节,'+TimetoStr(Now()))
      else if (FileSize > 1024) and (FileSize < (1024*1024)) then
        MainForm.mmo_Report.Lines.Add('☆开始接收文件:'+FileName+',长度'+inttostr(FileSize div 1024)+'KB,'+TimetoStr(Now()));
      {else if  (FileSize > (1024*1024)) then
        MainForm.mmo_Report.Lines.Add('☆开始接收文件:'+FileName+',长度'+inttostr(FileSize div (1024*1024))+'MB,'+TimetoStr(Now())); }
      Echo(1);
    end;
      

  7.   

    delphi下windows核心编程
    好好看看把