本文整理自网络,侵删。
来源 https://bbs.csdn.net/topics/390985048
分配一块大内存吧,要是一下申请不了64M那么大,就多申请几块小的,用个链表连起来。用FileStream类的方法读取文件内容。
varstrList:TStringList;beginstrList:=TStringList.Create;strList.LoadFromFile('Filepath');//这样就读到内存中,保存在变量strList中了,要用的时候可以用strList.text取出end;文件流、
var mStream: TMemoryStream;begin mStream := TMemoryStream.Create; mStream.LoadFromFile('c:\temp\test.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),这样不会造成内存浪费,也符合软件开发的基本逻辑。
相关阅读 >>
Delphi win32_diskdrive 硬盘 参数说明
Delphi 从listview组件中的选定行在数据库中删除
更多相关阅读请进入《Delphi》频道 >>