`
dkn28dkn
  • 浏览: 17914 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

内存映射对于大文件的使用

 
阅读更多

内存映射对于大文件的使用
2011年04月28日
  平时很少使用大文件的内存映射,碰巧遇到了这样的要求,所以把过程记录下来,当给各位一个引子吧,因为应用不算复杂,可能有考虑不到的地方,欢迎交流。
  对于一些小文件,用普通的文件流就可以很好的解决,可是对于超大文件,比如2G或者更多,文件流就不行了,所以要使用API的内存映射的相关方法,即使是内存映射,也不能一次映射全部文件的大小,所以必须采取分块映射,每次处理一小部分。
  先来看几个函数
  CreateFile :打开文件
  GetFileSize : 获取文件尺寸
  CreateFileMapping :创建映射
  MapViewOfFile :映射文件
  看MapViewOfFile的帮助,他的最后两个参数都需要是页面粒度的整数倍,一般机器的页面粒度为64k(65536字节),而我们实际操作中,一般都不是这样规矩的,任意位置,任意长度都是可能的,所以就要做一些处理。
  本例的任务是从一个长度列表中(FInfoList),依次读取长度值,然后到另外一个大文件(FSourceFileName)中去顺序读取指定长度的数据,如果是小文件,这个就好办了,一次读到文件流中,然后依次读取就是了,大数对于大文件,就需要不断改变映射的位置,来取得我们想要的数据。
  本例中显示先通过GetSystemInfo来获取页面粒度,然后以10倍的页面粒度为一个映射数据块,在for循环中,会判断已经读取的长度(totallen)加上即将读取的长度,是否在本次映射范围之内(10倍的页面粒度),如果在就继续读取,如果超出了,就要记下剩下的数据,然后重新映射下一块内存,并将记录下的剩余数据合并到新读取的数据中,有点绕啊(可能是我的想法太绕了),下面列出代码。 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,FIL E_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMA L,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  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;  
分享到:
评论

相关推荐

    内存映射修改大文件_内存映射_MemoryFile_超大文件读写_

    在Windows系统中,可以使用CreateFileMapping和MapViewOfFile函数来创建和映射文件。在Linux中,相应的系统调用是mmap。这两个API都允许程序员指定文件的哪一部分映射到内存,以及映射的大小。一旦映射完成,程序就...

    VC++中使用内存映射文件处理大文件.doc

    3. **支持大文件**:对于那些无法完全加载到物理内存的大文件,内存映射文件提供了分页机制,只将当前需要的部分数据加载到内存中。 4. **多进程共享**:多个进程可以通过映射同一文件来实现数据共享,这比传统的IPC...

    大文件读写内存映射.rar

    需要注意的是,由于内存映射文件可能跨越多个页,所以部分写操作可能导致整个页被刷新到磁盘,这可能会有性能影响。 5. 关闭映射:完成操作后,使用`unmap`方法释放内存映射,然后关闭文件。这会确保所有未同步的...

    C++中使用内存映射文件处理大文件

    然而,使用内存映射文件也需要考虑一些注意事项,例如,如果文件过大,可能会超过进程的地址空间限制;另外,如果不正确地管理映射和释放,可能导致资源泄露。因此,正确理解和使用内存映射文件的API函数是至关重要...

    使用内存映射修改大文件

    本文介绍利用内存映射文件修改大文件:在大文件内存前加入一段数据,若要使用内存映射文件,必须执行下列操作步骤: 1.创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件; 2.创建一个文件...

    使用内存映射处理大文件

    使用内存映射文件处理大文件主要包括以下几个步骤: 1. **创建或打开文件**:使用 `CreateFile()` 函数创建或打开一个文件内核对象。 2. **创建文件映射对象**:使用 `CreateFileMapping()` 函数创建一个文件映射...

    内存映射读写文件的方法

    内存映射文件(Memory-Mapped File)是一种在操作系统层面上高效读写大文件的技术,它允许应用程序将文件的内容直接映射到进程的虚拟地址空间中,使得数据的读写如同操作内存一样快速。这种方式在处理大数据量时尤其...

    易语言内存映射大文件

    易语言内存映射大文件源码,内存映射大文件,创建映射,打开文件_,取颗粒数,映射内存,读基址,释放内存,关闭文件_,写入字节集,移动读写位置_,读位置指针,删除字节集,十六到十,映射_创建,API_取文件长度,API_打开文件,API...

    .net 4.0 中使用内存映射文件的方法

    ### .NET 4.0 中使用内存映射文件的方法 #### 概述 在.NET 4.0中,新增加了内存映射文件的支持,这为开发者提供了更加灵活且高效的方式来处理大型文件。通过内存映射文件技术,可以将文件映射到进程的虚拟地址空间...

    Delphi 中内存映射对于大文件的使用

    Delphi 中内存映射对于大文件的使用 Delphi 中内存映射对于大文件的使用是指在 Delphi 编程中使用内存映射来处理大文件的技术。这种技术可以将大文件分割成小块,逐步读取和处理,从而避免了大文件的内存溢出问题。...

    VC++中使用内存映射文件处理大文件

    ### 使用VC++中的内存映射文件处理大文件 #### 概述 文件操作是软件开发中最常见的需求之一,尤其在需要处理大型数据集的应用场景下更为关键。传统的文件读写方法(例如`CreateFile()`、`ReadFile()`、`WriteFile...

    使用内存映射文件加快文件操作速度

    通过使用内存映射文件,可以显著提高文件操作的速度和效率,特别是在处理大文件时优势更加明显。在VB开发环境中,虽然传统的方法也可以实现文件读写,但采用内存映射文件的方式无疑能够带来更好的性能表现。希望本文...

    用内存映射文件方法处理大文件

    4. **大文件处理**:对于大文件,内存映射文件特别有用,因为它可以按需加载数据,不必一次性将整个文件加载到内存,避免了内存不足的问题。 5. **原子性操作**:在某些操作系统中,对映射内存的写操作可能具有原子...

    C# - 使用内存映射文件的高效文件 I/O

    我们使用创建或打开内存映射文件MemoryMappedFile.CreateFromFile。如果该文件不存在,则会创建该文件。我们使用创建内存映射视图访问器mmf.CreateViewAccessor()。该访问器允许我们有效地读取数据并将其写入内存...

    内存映射的使用——实现大文件内容倒序

    在Windows平台上,使用内存映射实现大文件内容倒序主要涉及以下几个关键步骤: 1. **打开文件**:首先,需要使用`CreateFile`函数打开目标文件,获取文件句柄。此函数提供了对文件的各种访问控制和共享模式,以及...

    Delph/XE如何应用共享内存映射文件(源代码)

    2. **Delphi中的内存映射文件实现**:在Delphi中,可以使用Windows API函数`CreateFileMapping`和`MapViewOfFile`来创建和访问内存映射文件。`CreateFileMapping`用于创建一个内存映射文件对象,`MapViewOfFile`则将...

    Visual C++ .NET环境下采用内存映射文件设计超大文件数据编辑器

    本文将深入探讨如何在Visual C++ .NET环境下使用内存映射文件设计一个能够处理超大文件数据的编辑器。 首先,我们要理解内存映射文件的基本概念。内存映射文件是一种技术,它允许程序将磁盘上的文件视作内存的一...

    VC中用内存映射文件处理大文件

    使用内存映射文件处理大文件时,系统会按页面单位进行数据传输,由虚拟内存管理器调度。当需要的数据不在物理内存中时,操作系统会自动将对应的磁盘页面调入内存,反之,如果内存紧张,会将不活跃的页面写回磁盘,...

    内存映射文件实现大数据量快速存储

    对于大数据量的文件,内存映射文件的优势更加明显。即使文件大于可用物理内存,操作系统也会根据需要按需加载和交换页面,使得程序可以处理远大于实际内存大小的文件,而不需要一次性全部加载到内存。 5. **并发...

    vc 内存映射文件.doc

    内存映射文件的工作原理类似于操作系统中的虚拟内存机制,只不过这里使用的不是页面文件,而是磁盘上的实际文件。简单来说,就是将磁盘上的文件映射到进程的地址空间内,之后对这段内存区域的操作就等同于对原文件的...

Global site tag (gtag.js) - Google Analytics