none
MemoryMappedFile и дозапись файла RRS feed

  • Вопрос

  • Проблема заключается в том, что непонятно как с помощью MemoryMappedFile записывать данные, которые увеличивают размер файла. Я пробовал использовать такой способ:

     

            fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            file = MemoryMappedFile.CreateFromFile(fs, ind, 100, MemoryMappedFileAccess.ReadWrite, new MemoryMappedFileSecurity(), HandleInheritability.Inheritable, false);
    
    

     

    когда необходимо увеличить размер:

     

    fs.SetLength(fs.Length + 100);
    
    Но при создании file.CreateViewAccessor вываливается исключение. Складывается впечатление что file изменение размера не заметил. Если заново пересоздавать MemoryMappedFile то исключение не возникает.

     

    27 января 2011 г. 1:23

Ответы

  • Не видел такого вопроса в этом топике. Видел только "почему такой способ не работает", на него я вроде ответил :)

    Ответ на вопрос "как производить дозапись" - в первом сообщении. Пересоздавать MMF с новым размером. Если файл растет постоянно - то пересоздавать сразу с запасом, на несколько тысяч item-ов. Примерно так поступает SQL Server, например - доращивает файл базы данных фиксированными кусками или кусками в % от текущего объема.


    My blog
    • Предложено в качестве ответа Abolmasov Dmitry 31 января 2011 г. 12:03
    • Помечено в качестве ответа Max Charp 31 января 2011 г. 19:52
    30 января 2011 г. 19:37

Все ответы

  • Проверил ваш код, у меня все работает без ошибок, размер файла увеличивается, данные в него нормально записываются. Что за исключение вы получаете? Какой .net framework используете?

    Попробуйте следующий код, будет ли он создавать исключение?

      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
        }
    
        FileStream fs;
        MemoryMappedFile file;
    
        private void button1_Click(object sender, EventArgs e)
        {
          string path = @"D:\test.txt";
          fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
          file = MemoryMappedFile.CreateFromFile(fs, "mapName1", fs.Length, MemoryMappedFileAccess.ReadWrite, new MemoryMappedFileSecurity(), HandleInheritability.Inheritable, false);
    
          using (MemoryMappedViewAccessor v = file.CreateViewAccessor())
          {
            v.WriteArray<char>(0, "test".ToCharArray(), 0, "test".Length);
          }
        }
    
        private void button2_Click(object sender, EventArgs e)
        {
          fs.SetLength(fs.Length + 100);
          using (MemoryMappedViewAccessor v = file.CreateViewAccessor())
          {
            v.WriteArray<char>(50, "hello".ToCharArray(), 0, "hello".Length);
          }
        }
      }
    

    Для связи [mail]
    28 января 2011 г. 11:00
  • Я имел ввиду примерно такой код:

     

        private void button1_Click(object sender, EventArgs e)
        {
          //string path = @"c:\test.txt";
          string path = @"c:\test\test.txt";
    
          var item_size = 16;
          var fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite);
          var file = MemoryMappedFile.CreateFromFile(fs, "mapName1", item_size, MemoryMappedFileAccess.ReadWrite, new MemoryMappedFileSecurity(), HandleInheritability.Inheritable, false);
          var chars = "test".ToCharArray();
    
          for (int i = 0; i < 1000; ++i)
          {
            var item = i * item_size;
            fs.SetLength(fs.Length + item_size);
    
            using (var v = file.CreateViewAccessor(item, item_size, MemoryMappedFileAccess.Write))
            {
              v.Write(0, i);
              v.WriteArray<char>(4, chars, 0, chars.Length);
            }
          }
        }
    
    в строке "using (var v = file.CreateViewAccessor...." на второй итерации возникает исключение "Access to the path is denied."

    28 января 2011 г. 16:41
  • Исключение System.UnauthorizedAccessExeption 

    Microsoft .NET Framework Version 4.0.30319 RTMRel
    
    28 января 2011 г. 16:46
  • Так вы подтверждаете наличие проблемы? Вероятно это баг в .Net
    29 января 2011 г. 14:40
  • Я подтверждаю наличие проблемы, и то, что это не баг в .NET :)

    Во первых, в примере неправильно рассчитывается offset, передаваемый в CreateViewAccessor. Но падает не из-за него.

    Во вторых, максимальный размер данных, доступных через MMF, задается 3-м параметром - Capacity - в CreateFromFile, а в примере туда передается item_size - 16 байт. Размер, конечно, округляется до размеров страницы, но все равно не превышает пары килобайт. 

    Получить доступ к данным за пределом Capacity, заданным при создании MMF, нельзя. В CreateFromFile стоит дополнительная проверка на случай размер файла > capacity. Переданный в качестве параметра FileStream используется только для этой проверки, получения SafeFileHandle, и закрытия файла при Dispose.

    Если размер файла на диске меньше, чем Capacity, файл принудительно увеличивается до Capacity.

    Подробно о поведении, задаваемом параметром capacity, можно почитать в описании API CreateFileMapping, в ремарках. Соответствующий параметр называется dwMaximumSize.


    My blog
    • Предложено в качестве ответа Abolmasov Dmitry 31 января 2011 г. 12:03
    30 января 2011 г. 16:13
  • Все правильно. За исключением ответа на вопрос, как производить дозапись файла.
    30 января 2011 г. 19:23
  • Не видел такого вопроса в этом топике. Видел только "почему такой способ не работает", на него я вроде ответил :)

    Ответ на вопрос "как производить дозапись" - в первом сообщении. Пересоздавать MMF с новым размером. Если файл растет постоянно - то пересоздавать сразу с запасом, на несколько тысяч item-ов. Примерно так поступает SQL Server, например - доращивает файл базы данных фиксированными кусками или кусками в % от текущего объема.


    My blog
    • Предложено в качестве ответа Abolmasov Dmitry 31 января 2011 г. 12:03
    • Помечено в качестве ответа Max Charp 31 января 2011 г. 19:52
    30 января 2011 г. 19:37