C# - Trabalhando com arquivos mapeados na memória


 Neste artigo veremos como trabalhar com arquivos mapeados na memória.

Um arquivo mapeado pela memória tem o conteúdo de um arquivo em memória virtual. Esse mapeamento entre um espaço de arquivo e a memória permite que um aplicativo, inclusive vários processos, modifique o arquivo ao ler e gravar diretamente na memória.

Dessa forma arquivos mapeados na memória permitem acessar arquivos ou compartilhar a memória de diferentes processos.

Existem diversos cenários e recursos com essa tecnologia:

Assim esse recurso fornece uma vantagem de desempenho. Ele pode ser encontrado no namespace System.IO.MemoryMappedFiles sendo um tipo de dados abstrato.

Há dois tipos de arquivos mapeados na memória:

A API de arquivos mapeados na memória permite usar um arquivo físico ou uma memória compartilhada - onde
o arquivo de paginação do sistema é usado como um armazenamento de apoio. A memória compartilhada pode ser maior que a memória física disponível , portanto, é necessário um suporte.

Com uma dessas opções, você pode atribuir um nome para o mapa de memória, e assim permitir que diferentes processos tenham acesso à mesma memória compartilhada.

Depois de criar o mapa de memória, você pode criar uma visualização. Uma visão é usada para mapear uma parte do arquivo completo de memória mapeada para acessá-lo para leitura ou escrita.

Temos a disposição os seguintes recursos para trabalhar com arquivos mapeados em memória:

Vejamos como isso funciona na prática.

Criando o projeto Console

Vamos criar  uma aplicação Console  App (.NET Core) usando o VS 2017 Community com o nome NetCore_MapFiles.

Inclua o código abaixo no arquivo Program.cs :

using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
namespace NetCore_MapFiles
{
    public struct MinhaCor
    {
        public short Red;
        public short Green;
        public short Blue;
        public short Alpha;
        // Torna a view mais brilhante
        public void Brilhante(short value)
        {
            Red = (short)Math.Min(short.MaxValue, (int)Red + value);
            Green = (short)Math.Min(short.MaxValue, (int)Green + value);
            Blue = (short)Math.Min(short.MaxValue, (int)Blue + value);
            Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            long offset = 0x10000000; // 256 megabytes
            long tamanho = 0x20000000; // 512 megabytes
            // criar um arquivo mapeado na memoria
            using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\dados\ArquivoMuitoGrande.data", 
                                                                FileMode.Open, "ImagemA"))
            {
                // Cria uma visualização de acesso aleatório, a partir do 256º megabyte (o deslocamento)
                // para o 768º megabyte (o deslocamento mais comprimento).
                using (var accessor = mmf.CreateViewAccessor(offset, tamanho))
                {
                    int colorSize = Marshal.SizeOf(typeof(MinhaCor));
                    MinhaCor cor;
                    // Faz alterações na view
                    for (long i = 0; i < length; i += colorSize)
                    {
                        accessor.Read(i, out cor);
                        cor.Brilhante(10);
                        accessor.Write(i, ref cor);
                    }
                }
            }
        }
    }
}

O método CreateFromFile cria um arquivo mapeado na memória de um arquivo existente no disco.

Ao invocar o método CreateViewAccessor retornamos um MemoryMappedViewAccessor para acessar a memória compartilhada. Com o view accessor, você pode definir um deslocamento e tamanho que é usado por esta tarefa. Claro, o tamanho máximo que você pode usar é o tamanho do arquivo de memória mapeado em si.

Podemos abrir o mesmo arquivo mapeado na memória para outro processo usando o código a seguir:

           // Assume que outro processo criou o arquivo mapeado na memória
            using (var mmf = MemoryMappedFile.OpenExisting("ImagemA"))
            {
                using (var accessor = mmf.CreateViewAccessor(4000000, 2000000))
                {
                    int colorSize = Marshal.SizeOf(typeof(MinhaCor));
                    MinhaCor color;
                    // Faz mudanças na view
                    for (long i = 0; i < 1500000; i += colorSize)
                    {
                        accessor.Read(i, out color);
                        color.Brilhante(20);
                        accessor.Write(i, ref color);
                    }
                }
            }

Aqui usamos o método OpenExisting que abre um arquivo mapeado em memória nomeado existente na memória
do sistema.

Pegue o código projeto aqui:  NetCore_MapFiles.zip

(disse Jesus) - "Porque por tuas palavras serás justificado, e por tuas palavras serás condenado."
Mateus 12:37

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

Referências:


José Carlos Macoratti