Файлы, отображаемые в память

41

Для тех, кто имел дело только с управляемым кодом, файлы, отображаемые в память (memory mapped file — MMF), могут быть новым понятием. В .NET Framework 4 файлы MMF являются частью набора инструментов для построения приложений и находятся в новом пространстве имен System.IO.MemoryMappedFiles.

Использовать файлы MMF можно было всегда за счет выполнения вызовов платформы (P/Invoke) Windows API, а с появлением пространства имен System.IO.MemoryMappedFiles работа с файлами MMF стала возможной в управляемом коде.

Файлы MMF являются практически идеальным решением, когда приложению требуется частый или произвольный доступ к файлам. При таком подходе можно загружать часть или весь файл в сегмент виртуальной памяти, где он выглядит для приложения так, будто бы содержится в основной памяти.

Интересно также то, что этот файл в памяти можно использовать в качестве общего ресурса, доступного более чем одному процессу. Ранее с помощью Windows Communication Foundation (WCF) или Named Pipes можно было организовать взаимодействие с общим ресурсом из нескольких процессов, а теперь появилась возможность обеспечить совместное использование файла MMF процессами с использованием общего имени.

При работе с файлами MMF приходится иметь дело с двумя объектами. Первым является экземпляр файла MMF, который загружает файл, а вторым — объект, обеспечивающий доступ к нему. В следующем коде выполняется запись в объект файла MMF, а затем его чтение. Кроме того, запись также происходит и при освобождении объекта:

using System;
using System.IO.MemoryMappedFiles;
using System.Text;

namespace MemoryFiles
{
    class Program
    {
        static void Main()
        {
            using (var mmFile = MemoryMappedFile.CreateFromFile(
                @"C:\myProject\ConsoleApplications\MemoryFiles\test.txt",
                System.IO.FileMode.Create, "fileHandle", 1024 * 1024))
            {
                string valueToWrite = "Запись MMF " + DateTime.Now.ToString();
                var myAccessor = mmFile.CreateViewAccessor();

                myAccessor.WriteArray(0, 
                    Encoding.ASCII.GetBytes(valueToWrite), 0, valueToWrite.Length);
                var readOut = new byte[valueToWrite.Length];
                myAccessor.ReadArray(0, readOut, 0, readOut.Length);
                var finalValue = Encoding.ASCII.GetString(readOut);
                Console.WriteLine("Message: " + finalValue);
                Console.ReadLine();
            }
        }
    }
}

В данном случае отображаемый в память объект создается из физического файла с помощью метода CreateFromFile(). Помимо самого файла MMF необходимо создать также и объект для доступа к нему. Это делается следующим образом:

var myAccessor = mmFile.CreateViewAccessor();

После создания объекта для доступа можно переходить непосредственно к записи или чтению.

Класс MemoryStream

Иногда оказывается полезно читать вводимые данные из массива или записывать выводимые данные в массив, а не вводить их непосредственно из устройства или выводить прямо на него. Для этой цели служит класс MemoryStream. Он представляет собой реализацию класса Stream, в которой массив байтов используется для ввода и вывода. В классе MemoryStream определено несколько конструкторов. Ниже представлен один из них:

MemoryStream(byte[] buffer)

где buffer обозначает массив байтов, используемый в качестве источника или адресата в запросах ввода-вывода. Используя этот конструктор, следует иметь в виду, что массив buffer должен быть достаточно большим для хранения направляемых в него данных.

Пройди тесты
Лучший чат для C# программистов