Search code examples
c#structmemory-mapped-filesmemory-mapping

How to use MemoryMappedViewAccessor properly?


I'm really trying to understand how to use memory-mapped files properly, but I'm having some issues. Here's the scenario:

I have some large files, anywhere from 1-10 GB. These are composed of structs, all 128 bytes except the very first one of the file.

I need random access to any one of these structs fast, which from what I read is what a memory-mapped file is perfect for. I also need these memory-mapped files to be able to be opened by other processes, but there won't be any writing, just reading of the file.

I am able to determine the byte offset of the exact struct I need to read.

First I tried making the mem-mapped file like so:

MemoryMappedFile hFileMapping = MemoryMappedFile.CreateFromFile(rampPath, FMode, Path.GetFileNameWithoutExtension(rampPath), GetFileLength(rampPath), access);

However, other processes couldn't open it. So I found that there was another constructor that took in a FileStream. So I changed it to this:

FileStream fs = new FileStream(rampPath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read);
MemoryMappedFile hFileMapping = MemoryMappedFile.CreateFromFile(fs, Path.GetFileNameWithoutExtension(rampPath), GetFileLength(rampPath), access, null, HandleInheritability.Inheritable, true);

Other processes could open the mem-mapped file now. Then I try making a view of the mapped file:

MemoryMappedViewAccessor hFileAccessor = hFileMapping.CreateViewAccessor(0, GetFileLength(rampPath), MemoryMappedFileAccess.Read));

This is fine if the files are small, but if they are large I get out of storage and memory exceptions.

So I need to map only a portion of the file at one time, but what is the best way to determine if the struct I'm looking for is in the currently mapped view? Do I keep track of the current mapped view's offset and length and see if the offset of the struct is in there? Is there a better way to go about all this?


Solution

  • Thanks to @Ross Bush in the OP's comments for the suggestions.

    What I did was just make the ViewAccessor's capacity a set amount always. And since I have the byte offset I need, I just ran some calculations to determine if the byte offset was inside the ViewAccessor or not. If it wasn't, then change the ViewAccessor to a different offset/capacity so the byte offset fell within it.