Search code examples
c#memory-mapped-files

MemoryMappedFile: Unable to find the specified file


I'm having trouble getting the MemoryMappedFile pattern to work. I have a directory with 25 excel spreadsheets that I want to load using MemoryMappedFile. The MemoryMappedFile.CreateFromFile works just fine, but when I call MemoryMappedFile.OpenExisting(lender), it reads the first 3 files, and then on the 4th attempt, it fails with exception:

Unable to find the specified file.

public static void Main()
{
    var files = System.IO.Directory.EnumerateFiles(@"lendersheets", "*.xls*").ToList();
    foreach (var file in files)
    {
        var lender = System.IO.Path.GetFileNameWithoutExtension(file);

        MemoryMappedFile.CreateFromFile(file, FileMode.Open, lender);
    }

    foreach (var file in files)
    {
        var lender = System.IO.Path.GetFileNameWithoutExtension(file);

        using (var mmfExisting = MemoryMappedFile.OpenExisting(lender))
        {
            var stream = mmfExisting.CreateViewStream();
            if (stream.CanRead && stream.CanWrite)
            {
                LoadFromStream(stream);
            }
        }                              
    }
}

UPDATE:

I have noticed that when I remove the LoadFromStream method call, the exception doesn't occur anymore. Here is the logic for LoadFromStream:

    private static object LoadFromStream(Stream stream)
    {
        hssfwb = new HSSFWorkbook(stream);
        evaluator = new HSSFFormulaEvaluator(hssfwb);

        return hssfwb;
    }

Solution

  • I ended up doing the following. I have one singleton instance of a collection of all files in Memory. I then create a new instance of the memory stream when I need to use the specific file in memory for calculations:

    private static readonly Dictionary<string, MemoryStream> _lenderPolicyFileStreams = new Dictionary<string, MemoryStream>();
    
            private static void CreateLenderPolicyFileStreams()
            {
                string appDataPath = HostingEnvironment.MapPath("~/App_Data");
                var files = Directory.EnumerateFiles(appDataPath, "*.xls*").ToList();
    
                foreach (var file in files)
                {
                    var lenderName = Path.GetFileNameWithoutExtension(file);
    
                    // Create a file stream
                    var bytes = File.ReadAllBytes(file);
                    var stream = new MemoryStream(bytes);
    
                    // Add file stream to singleton collection
                    if (lenderName != null) 
                        _lenderPolicyFileStreams.Add(lenderName, stream);
                }
            }
    
            public static Stream GetMemoryStreamByLenderName(string lender)
            {
                MemoryStream fetchedStream;
                _lenderPolicyFileStreams.TryGetValue(lender, out fetchedStream);
    
                if (fetchedStream == null)
                    throw new Exception("Cannot find specified file stream by lender name");
    
                var clone = CloneStream(fetchedStream);
                return clone;
            }
    
            private static MemoryStream CloneStream(MemoryStream fileStream)
            {
                var memoryStream = new MemoryStream();
    
                fileStream.Position = 0;
                fileStream.CopyTo(memoryStream);
                memoryStream.Position = 0;
    
                return memoryStream;
            }