Usually rarely use large file memory mapping, happened to meet such requirements, so the process is recorded, when giving you a primer, because the application is not complicated, there may be no consideration of the place, welcome to exchange.
For some small files, with ordinary file stream can be a good solution, but for large files, such as 2G or more, the file stream is not, so to use the API's memory mapping method, even the memory map, can not map the size of all files at once, so you must take a block map, Handle a small portion at a time.
Let's look at a few functions
CreateFile: Open File
GetFileSize: Get File size
CreateFileMapping: Creating Mappings
MapViewOfFile: Mapping File
See MapViewOfFile's help, his last two parameters all need to be the page granularity of the integer times, the general machine page granularity of 64k (65536 bytes), and we actually operate, is generally not such rules, arbitrary position, arbitrary length is possible, so we have to do some processing.
The task of this example is from a length list (finfolist), read the length value sequentially, and then go to another large file (Fsourcefilename) to read the specified length of the data, if it is a small file, this is good, once read the file stream, and then read it sequentially, Large numbers for large files, you need to constantly change the location of the map to get the data we want.
This example shows that the page granularity is obtained by GetSystemInfo, and then 10 times times the page granularity as a mapped block, in the for loop, the length of the read (Totallen) plus the length to be read, whether within this mapping range (10 times times the page granularity), If you continue to read, if it is exceeded, write down the rest of the data, then remap the next piece of memory, and then merge the remaining data from the record into the newly read data, a little bit around (maybe my idea is too wrapped up), the code listed below.
[Delphi]View Plaincopy
- 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;
- //Get System Information
- GetSystemInfo (SysInfo);
- //page allocation granularity size
- BlockSize: = SysInfo. dwallocationgranularity;
- //Open File
- 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;
- //Get file size
- FileSize: = GetFileSize (Ffile_handle,nil);
- //Create Mappings
- Ffile_map: = CreateFileMapping (Ffile_handle,nil,page_readonly,0,0,Nil);
- if Ffile_map = 0 then Exit;
- //Here we have 10 times times blocksize is mapped to a data block, and if the file size is less than 10 times times blocksize, the entire file length is mapped directly
- if filesize div blocksize > ten Then
- Readlen: = 10*blocksize
- Else
- Readlen: = FileSize;
- For i: = 0 to finfolist. Count- 1 do
- begin
- List. Delimiter: = ': ';
- List. Delimitedtext: = Finfolist. Strings[i];
- //Get length, I've done the parsing here because I've stored the information for A:B:C this type, so separated by: number
- Len: = Strtoint (List. strings[1]);
- Interval: = Strtoint (List. strings[2]);
- if (i = 0) or (Totallen+len >=readlen) Then
- begin
- //If the length of the read plus the length that is about to be read is greater than 10 times times blocksize, then we want to keep the contents of the previous mapping to merge with the newly mapped content
- if i > 0 Then
- begin
- Offset: = offset + Readlen;
- //write temporary stream
- Tstream. Write (P^,readlen-totallen);
- Tstream. Position: = 0;
- end;
- //If the length of the unread data is not enough for one allocation granularity, then the remaining length is mapped directly
- if Filesize-offset < blocksize Then
- Readlen: = Filesize-offset;
- //Map, p is a pointer to the map area
- //Note here The third parameter, always set to 0, this value is set according to the actual situation
- P: = PChar (MapViewOfFile (Ffile_map,file_map_read,0,offset,readlen));
- end;
- //If there is data in the staging stream, you need to merge
- if Tstream. Size > 0 Then
- begin
- //Copy the temporary stream data.
- Stream. CopyFrom (Tstream,tstream. Size);
- ///Then write new data at the end, merge complete
- Stream. Write (P^,len-tstream. Size);
- Totallen: = Len-tstream. Size;
- //Move the position of the pointer, pointing to the beginning of the next data
- INC (P,len-tstream. Size);
- Tstream. Clear;
- End
- Else
- begin
- Stream. Write (P^,len);
- Totallen: = Totallen + len;
- INC (P,len);
- end;
- Stream. Position: = 0;
- //Save the stream as a file
- Stream. SaveToFile (IntToStr (i) +'. txt ');
- Stream. Clear;
- end;
- finally
- Stream. Free;
- Tstream. Free;
- CloseHandle (Ffile_handle);
- CloseHandle (FFILE_MAP);
- end;
- End
http://blog.csdn.net/bdmh/article/details/6369250
Memory mapping for large file usage