• delphi中如何将一整个文件读入内存


    来源 https://bbs.csdn.net/topics/390985048

    分配一块大内存吧,要是一下申请不了64M那么大,就多申请几块小的,用个链表连起来。
    用FileStream类的方法读取文件内容。

    var
    strList:TStringList;
    begin
    strList:=TStringList.Create;
    strList.LoadFromFile('Filepath');//这样就读到内存中,保存在变量strList中了,要用的时候可以用strList.text取出
    end;

    文件流、

    var
      mStream: TMemoryStream;
    begin
      mStream := TMemoryStream.Create;
      mStream.LoadFromFile('c:	emp	est.txt');          {把文件读入内存流}
      Memo1.Lines.LoadFromStream(mStream);      {把内存流载入 Memo1}

    用内存映射最好,TMemoryStream坑爹呢,整个64M到内存去?要是上G文件也这样整?TFileStream比较慢,内存映射最快,大致是CreateFile获得文件句柄,再 CreateFileMapping 创建映射 ,然后根据大小一块一块MapViewOfFile ,得到的内存地址可以直接访问,效率绝对可以。

    PShareMem = ^TShareMem;
      TShareMem = Record
        id:string[10];
        name:string[20];
        age:Integer;
      end;
       
      shareMemName:string; //共享内存名
        fileHandle : THandle;//内存映射文件句柄
        pUserInfoShareMem : PShareMem;//指向共享内存的指针
         
        begin
       //创建“内存映射文件”
       fileHandle:=CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TShareMem), PChar(shareMemName));
       if fileHandle <> 0 then
       begin
         Self.Memo1.Lines.Add('已成功创建内存映射文件!');
       end;
    end;
     
     
    //将“内存映射文件”与“应用程序地址空间”建立映射关系
      pUserInfoShareMem:=MapViewOfFile(fileHandle,FILE_MAP_ALL_ACCESS,0,0,sizeof(TShareMem));
      if pUserInfoShareMem <> nil then
      begin
         Self.Memo1.Lines.Add('已成功建立映射关系!');
      end;
       
       
      pUserInfoShareMem.id:='8888';
       pUserInfoShareMem.name:='Terry';
       pUserInfoShareMem.age:=25;
       Self.Memo1.Lines.Add('已向共享内存中写入用户信息!');
        
       //解除“内存映射文件”与“应用程序地址空间”的映射关系
      if pUserInfoShareMem<> nil then
         UnmapViewOfFile(pUserInfoShareMem);
      Self.Memo1.Lines.Add('已成功解除映射关系!');
       
      //关闭内存映射文件
      if fileHandle<> 0 then
         CloseHandle(fileHandle);
      Self.Memo1.Lines.Add('已成功关闭内存映射文件!');

    用内存映射吧, 64G读进来都不成问题

    function FastReadFile(FileName: string): Integer;
    const
      PAGE_SIZE = 4 * 1024; //映射块大小不易过大,尽量以4k对齐
    var
      hFile: THandle;
      szHigh,szLow: DWORD;
      szFile,ps: Int64;
      hMap: THandle;
      hData: Pointer;
      dwSize: Cardinal;
    begin
      Result := -1;
      hFile := 0;
      hMap := 0;
      hData := nil;
      szHigh := 0;
      try
        //打开已存在的文件,获得文件句柄
        hFile := CreateFile(PChar(FileName),GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,
          nil,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
        if hFile = 0 then
        begin
          Result := GetLastError;
          Exit;
        end;
        //获取文件大小
        hMap := 0;
        hData := nil;
        szHigh := 0;
        szLow := GetFileSize(hFile,@szHigh);
        szFile := szLow or (szHigh shl 32);
        //创建映射句柄
        hMap := CreateFileMapping(hFile, nil, PAGE_READWRITE, szHigh, szLow, nil);
        if hMap = 0 then
        begin
          Result := GetLastError;
          Exit;
        end;
        ps := 0;
        //文件可能比较大,分块进行映射
        while ps < szFile do
        begin
          //计算映射大小及位置
          if szFile - ps > PAGE_SIZE then
            dwSize := PAGE_SIZE
          else
            dwSize := szFile - ps;
          szLow  := ps and $FFFFFFFF;
          szHigh := ps shr 32;
          //进行映射
          hData := MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,szHigh,szLow,dwSize);
          if hData = nil then
            Break;
          try
            //此时文件偏移ps处的数据通过hData即可读取到,块大小为dwSize
            //以下加上你读取的代码,可以做一个回调函数
            //比如你要当前位置的数据(取文件数)拷到指定内存处 CopyMemory(目标地址指针,hData,dwSize);
            //
     
     
     
     
     
     
          finally
            //移动文件偏移位置
            ps := ps + dwSize;
            //释放映射块
            UnmapViewOfFile(hData);
            hData := nil;
          end;
        end;
      finally
        //释放必要资源
        if hData <> nil then
          UnmapViewOfFile(hData);
        if hMap <> 0 then
          CloseHandle(hMap);
        if hFile <> 0 then
          CloseHandle(hFile);
      end;
    end;

    C# 读取大文件至内存

    long offest = 0;
                byte[] buffer = null;
                try
                {
                    using (FileStream fs = new FileStream(fileFullPath, FileMode.Open))
                    {
                        buffer = new byte[1024 * 1024];
                        while ((offest + 1024 * 1024) <= fs.Length)
                        {
                            fs.Read(buffer, 0, buffer.Length);
                            offest += 1024 * 1024;
                            fs.Seek(offest, SeekOrigin.Begin);
                        }
     
                        
     
                        if ((fs.Length - offest) < 1024 * 1024)
                        {
                            fs.Read(buffer, 0, Convert.ToInt32(fs.Length - offest));
                            MessageBox.Show("Done");
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }

    因为计算机的内存空间是有限的,如果一次性把大数据文件加载至内存,会造成内存极速被消耗。此举不适合一般情况的读取大数据文件。
    C#提供了FileStream类来操作文件流,可以和Seek()函数一起循环读取文件中特定长度的数据(比如1M),这样不会造成内存浪费,也符合软件开发的基本逻辑。

  • 相关阅读:
    3D 图片播放焦点图插件Adaptor
    深入浅出 RPC
    深入浅出 RPC
    Fragment学习(一) :生命周期
    Activity学习(二):Activity的启动模式(转载)
    Activity学习(一):生命周期
    AsyncTask的使用
    Handler用法总结
    深入理解java泛型
    mysql多表连接和子查询
  • 原文地址:https://www.cnblogs.com/blogpro/p/11339815.html
Copyright © 2020-2023  润新知