
Code: Select all
; purebasic survival guide - pb3.94
; filemapping_1.pb - 06.06.2007 ejn (blueznl)
; http://www.xs4all.nl/~bluez/datatalk/purebasic.htm
;
; - file mapping
; - CreateFile_()
; - CloseHandle_()
; - CreateFileMapping_()
; - MapViewOfFile_()
; - UnMapViewOfFile_()
;
; you DEFINITELY want to have the WIN32.HLP file open and at your side, jump to a page called 'File Mapping' and check on
; the subsequent pages
;
; windows offers a mechanism which maps files to (virtual) memory, whenever you change something in that memory,
; that change will be reflected in the file
;
; a program can have multiple views on a (mapped) file, and their contents will all be consistent when accessed through
; the mapping mechanism, all the (mapped) file data will be in memory thus speeding up access, and finally all data
; in that file can be processed as if it was memory
;
; WARNING! Windows NT and Windows 95 have certain restrictions, that may not be covered below (tested on XP only)
;
;
; *** creating a file using winapi calls...
;
; (simple winapi stuff, but we need it later, so let's first look at this)
;
; create a file for exclusive use
;
file_name.s = "testfile.dat" ; name of file to create
file_h = CreateFile_(@file_name,#GENERIC_READ|#GENERIC_WRITE,0,0,#CREATE_ALWAYS,0,0) ; open the file, empty it if it already existed
If file_h = #INVALID_HANDLE_VALUE Or file_h = 0 ; things went bonkers...
Debug "error creating file"
EndIf
;
; now put some data in it
;
bytes_written.l = 0 ; placeholder in memory where WriteFile_() can store the number of bytes written
For n = 1 To 10360
buffer.s = "this is line "+RSet(Str(n),4)+Chr(13)+Chr(10) ; create some data that we can write to the file
result = WriteFile_(file_h,@buffer,Len(buffer),@bytes_written,0) ; write the data to the file
Next n
;
; and close the file
;
CloseHandle_(file_h)
;
;
; *** granularity
;
; before we delve deeper into filemapping we have to understand a basic building block: system granularity, or
; allocation granularity: this is the smallest block the memory manager can handle or map, and depends on your
; operating system and hardware
;
; certain calls need this information, which can be obtained this way:
;
systeminfo.SYSTEM_INFO
GetSystemInfo_(@systeminfo)
system_granularity = systeminfo\dwAllocationGranularity
Debug "system granularity "+Str(system_granularity)+" bytes"
;
;
; *** filemapping
;
; mapping a file to memory offers us faster access, windows takes care of all caching
;
; let's start by opening an existing file
;
file_name.s = "testfile.dat" ; name of file to create
file_h = CreateFile_(@file_name,#GENERIC_READ|#GENERIC_WRITE,0,0,#OPEN_EXISTING,0,0) ; open an existing file
;
; now we map this file to (a part of) (virtual) memory
;
; when creating a file mapping object, we can specify the maximal size it can cover, this is NOT the buffer size it
; actually uses, it is the MAXIMAL buffer size it ever uses, by setting it to 0 it will be at max the CURRENT size
; of the specified file, check also WIN32.HLP for limitations of NT and 95...
;
; notice that CreateFile_(), CreateFileMapping_() and MapViewOfFile_() must have matching parameters
;
filemap_name.s = "testmap.dat" ; we give the mapping a name, though there isn't a real need here
filemap_h = CreateFileMapping_(file_h,0,#PAGE_READWRITE,0,0,@filemap_name) ; this creates an object that can map memory to the file
;
; with MapViewOfFile_() we specify a 'floating window' that peeks somewhere into the specified file, we can specify where
; this 'view' looks at, and how large it is
;
; MapViewOfFile_( <object_handle> , <access type> , <offset hi> , <offset lo> , <view size> )
;
; the pointers is 64 bit value, split up over a low and high part, and must be multiples of the allocation granularity
; (aka system granularity)
;
mapview_h = MapViewOfFile_(filemap_h,#FILE_MAP_WRITE,0,0,system_granularity) ; creates a map which points to the beginning of the file
;
; the returned handle is also the memory address where we can find the mapped data, let's find out what the first 100 bytes
; of the file contained
;
Debug PeekS(mapview_h,100) ; show 100 bytes
UnmapViewOfFile_(mapview_h) ; and be done
;
; unfortunately there is no way to 'move' a view, we first have to delete the old one and create a new one
; we have to be carefull that we won't 'overrun' the file, ie. the map should stay within the boundaries of the file
;
; in other words, we 'carve up' the file in multiple blocks of size 'system_granularity', ie. the specified offset
; must be a mutliple of system_granularity
;
; we must also make sure that the last byte of the view stays within the size specified with CreateFileMapping_(),
; this may mean we have to make the view smaller than system_granularity when reaching the end of the file
;
; let's do some fancy graphics :-) the '-' indicate the file, the 'x' indicate the view
;
; ----- xxxxx ---
; ----- ----- xxx
;
; note: whilst sizes specified with CreateFileMapping_() MAY allocate PHYSICAL memory up to the specified size, Windows
; will not keep the data at any cost in memory, and may write it out to the file itself, the view size specified with
; MapViefOfFile_() WILL most likely take up physical memory and certainly take up virtual memory, and is limited by
; the specified virtual memory settings
;
; super large view sizes may slow down your system and may cause problems, yet sizes too small will decrease the
; efficiency of file mapping... you decide what is an appropriate size :-)
;
position = FileSize(file_name)-200 ; let's move to the end of the file
mapoffset = position - (position % system_granularity) ; make sure we start on a multiple of system granularity
viewoffset = position - mapoffset ; where can we find the requested data in the view?
viewsize = FileSize(file_name) - mapoffset ; how much file is left?
If viewsize > system_granularity ; please, fred, give us Min() and Max()
viewsize = system_granularity
EndIf
mapview_h = MapViewOfFile_(filemap_h,#FILE_MAP_WRITE,0,mapoffset,viewsize)
Debug "view points to position "+Str(mapoffset)+" in file"
Debug "view size "+Str(viewsize)
Debug "requested data starts in file at "+Str(position)
Debug "and in memory (view) at "+Str(viewoffset)
Debug PeekS(mapview_h+viewoffset,100)
;
; ok, we're done, time to clean up
;
UnmapViewOfFile_(mapview_h)
CloseHandle_(filemap_h)
CloseHandle_(file_h)
;
; and to verify the result
;
OpenFile(1,file_name)
FileSeek(position)
buffer.s = Space(100)
ReadData(@buffer,100)
Debug buffer
CloseFile(1)
;