Как должен быть разработан класс, который упаковывает и предоставляет доступ к одному файлу? - PullRequest
1 голос
/ 25 августа 2010

MyClass это все о предоставлении доступа к одному файлу.Он должен CheckHeader(), ReadSomeData(), UpdateHeader(WithInfo) и т. Д.

Но поскольку файл, который представляет этот класс, очень сложен, он требует особых конструктивных соображений.

Этот файл содержит потенциально огромную древовидную структуру в виде папок с различными типами узлов и основан на блоках / ячейках для лучшей обработки фрагментации.Размер обычно меньше 20 МБ. Это не мой дизайн.

Как бы вы спроектировали такой класс?

  • Считать поток ~ 20 МБ в память?
  • Поместить копию в временный каталог и сохранить его путь в качестве свойства?

  • Хранить копии больших вещей в памяти и выставлять их как свойства только для чтения?
  • GetThings() из файла с кодом исключения?

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

(Это вопрос по дизайну, но платформа - .NET, а класс предназначен для автономного доступа к реестру для XP)

Ответы [ 2 ]

3 голосов
/ 05 сентября 2010

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

Если, однако, вам нужно выполнить различные действия с файлом, кроме одного линейного анализа, я бы проанализировал данные в облегченной базе данных, такой как SQLite, и затем поработал с этим. Таким образом, вся структура вашего файла будет сохранена, и все последующие операции с файлом будут выполняться быстрее.

1 голос
/ 09 сентября 2010

Доступ к реестру довольно сложный. Вы в основном читаете большое двоичное дерево. Дизайн класса должен сильно зависеть от хранимых структур данных. Только тогда вы сможете выбрать подходящий дизайн класса. Чтобы оставаться гибким, вы должны смоделировать примитивы, такие как REG_SZ, REG_EXPAND_SZ, DWORD, SubKey, .... Дон Сайм имеет в своей книге Expert F # хороший раздел о двоичном разборе с помощью двоичных комбинаторов. Основная идея заключается в том, что ваши объекты сами знают, как десериализовать из двоичного представления. Когда у вас есть поток байтов, который имеет такую ​​структуру



</ Node2>

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

public class Header
{
   static Header Deserialize(BinaryReader reader)
   {
      Header header = new Header();

      int magic = reader.ReadByte();
      if( magic == 0xf4 ) // we have a node entry
         header.Insert(Node.Read( reader );
      else if( magic == 0xf3 ) // directory entry
         header.Insert(DirectoryEntry.Read(reader))
      else 
         throw NotSupportedException("Invalid data");

      return header;
   }
}

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

Поскольку реестр в Windows может стать достаточно большим, невозможно сразу полностью прочитать его в память. Вам нужно будет разбить его на части. Одно из решений, которое применяет Windows, заключается в том, что весь файл размещается в памяти выгружаемого пула, которая может занимать несколько гигабайт, но только фактически доступные части выгружаются с диска в память. Это позволяет Windows эффективно обрабатывать очень большой файл реестра. Вам понадобится нечто подобное и для вашего читателя. Ленивый синтаксический анализ является одним из аспектов, и возможность перескочить в файле без необходимости читать промежуточные данные крайне важна для поддержания производительности.

Больше информации о выгружаемом пуле и реестре можно найти там: http://blogs.technet.com/b/markrussinovich/archive/2009/03/26/3211216.aspx

Ваш Api-дизайн будет зависеть от того, как вы считываете данные, чтобы оставаться эффективными (например, используйте отображенный в память файл и считываете из разных отображаемых областей). В .NET 4 появилась реализация файла Memory Mapped, которая в настоящее время неплоха, но существуют также обертки вокруг API-интерфейсов ОС.

С уважением, Алоис Краус

Для поддержки отложенной загрузки из файла с отображением в память имеет смысл не считывать байтовый массив в объект и анализировать его позже, а делать один шаг вперед и сохранять только смещение и длину фрагмента памяти из файла, отображаемого в память , Позже, когда объект действительно доступен, вы можете прочитать и десериализовать данные. Таким образом, вы можете пройти весь файл и построить дерево объектов, которое содержит только смещения и ссылку на файл, отображенный в памяти. Это должно сэкономить огромное количество памяти.

...