Существуют ли альтернативы для создания больших кроссплатформенных файлов-контейнеров?

StackOverflow https://stackoverflow.com/questions/257832

Вопрос

Раньше я спрашивал вопрос.

Проблема в том, что требования к нашей файловой структуре очень высоки.

Например, мы пытаемся создать контейнер, вмещающий до 4500 файлов и данных размером 500 МБ.

Файловая структура этого контейнера состоит из

  • База данных SQLite (до 1 МБ)
  • Текстовый XML-файл
  • Изображения внутри динамической структуры папок, составляющие остальные из 4500 файлов.

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

  • Небольшая база данных используется регулярно при доступе к контейнеру.

Tar, Zip и им подобные работают слишком медленно (даже при нулевом сжатии).Я знаю, что медленность — это субъективно, но распаковка контейнера такого размера занимает более 20 секунд.

Есть предположения?

Это было полезно?

Решение

Три вещи.

1) То, что сказал Тимоти Уолтерс, верно, я расскажу подробнее.

2) 4500 файлов и 500Мб данных - это просто много данных и записей на диск.Если вы работаете со всем набором данных, это будет медленно.Просто правда ввода-вывода.

3) Как уже отмечали другие, подробностей о варианте использования нет.

Если мы предположим, что сценарий с произвольным доступом только для чтения, то то, что говорит Тимоти, в значительной степени не соответствует действительности, и его реализация проста.

В двух словах, вот чем вы занимаетесь.

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

Затем вы объединяете два файла вместе.В простом случае сначала идет блок TOC, а затем блок данных.

Если вы хотите получить данные в этом формате, найдите в TOC имя файла, возьмите смещение от начала блока данных, добавьте размер блока TOC и прочитайте FILE_LENGTH байтов данных.Простой.

Если вы хотите быть умнее, вы можете поместить TOC в КОНЕЦ файла больших двоичных объектов.Затем добавьте в самом конце смещение к началу оглавления.Затем вы переходите к концу файла, резервируете 4 или 8 байтов (в зависимости от размера вашего числа), берете ЭТО значение и переходите еще дальше к началу вашего TOC.Тогда вы возвращаетесь к исходной точке.Вы делаете это для того, чтобы вам не пришлось вначале дважды пересобирать архив.

Если вы разложите оглавление блоками (скажем, размером 1 КБ), вы сможете легко выполнить двоичный поиск по оглавлению.Просто заполните каждый блок записями с информацией о файле, а когда у вас закончится место, напишите маркер, заполните нулями и перейдите к следующему блоку.Чтобы выполнить бинарный поиск, вы уже знаете размер оглавления, начните с середины, прочитайте первое имя файла и продолжайте дальше.Вскоре вы найдете блок, затем прочитаете его и просканируете в поисках файла.Это делает его эффективным для чтения без хранения всего оглавления в оперативной памяти.Другое преимущество заключается в том, что блокировка требует меньше дисковой активности, чем цепная схема, такая как TAR (где вам нужно сканировать архив, чтобы что-то найти).

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

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

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

Другие советы

Поскольку вы, кажется, выполняете произвольные операции с файловой системой в своем контейнере (скажем, создание, удаление новых файлов в контейнере, перезапись существующих файлов, добавление), я думаю, вам следует выбрать какую-то файловую систему.Выделите большой файл, затем создайте в нем структуру файловой системы.

Доступно несколько вариантов файловой системы:как для Berkeley UFS, так и для Linux ext2/ext3 доступны библиотеки пользовательского режима.Также возможно, что вы где-нибудь найдете реализацию FAT.Убедитесь, что вы понимаете структуру файловой системы, и выберите ту, которая допускает расширение - я знаю, что ext2 довольно легко расширить (с помощью другой группы блоков), а FAT расширить сложно (необходимо добавить к FAT).

В качестве альтернативы вы можете разместить формат виртуального диска еще ниже файловой системы, что позволит произвольно переназначать блоки.Тогда на диске не обязательно будут появляться «свободные» блоки файловой системы, и вы сможете выделить виртуальный диск значительно большего размера, чем будет реальный файл-контейнер.

Исходя из предположения, что вам понадобится доступ только для чтения к файлам, почему бы просто не объединить их все вместе и создать второй «индексный» файл (или индекс в заголовке), который сообщит вам имя файла, начните положение и длина.Все, что вам нужно сделать, это найти начальную точку и прочитать правильное количество байтов.Этот метод будет варьироваться в зависимости от вашего языка, но в большинстве из них он довольно прост.

Самым сложным становится создание файла данных + индекса, и даже это довольно просто!

Образ диска ISO может помочь.Он должен легко хранить такое количество файлов и поддерживается многими программами во всех основных операционных системах.

Во-первых, спасибо за расширение вашего вопроса, это очень помогает дать лучшие ответы.

Учитывая, что вам в любом случае понадобится база данных SQLite, оценили ли вы производительность помещения всего этого в базу данных?Мой опыт основан на SQL Server 2000/2005/2008, поэтому я не уверен в возможностях SQLite, но уверен, что это будет довольно быстрый вариант для поиска записей и получения данных, в то же время позволяющий удалять и/или параметры обновления.

Обычно я бы не рекомендовал помещать файлы в базу данных, но, учитывая, что общий размер всех изображений составляет около 500 МБ для 4500 изображений, вы просматриваете чуть более 100 КБ на изображение, верно?Если вы используете динамический путь для хранения изображений, то в немного более нормализованной базе данных вы можете иметь таблицу «ImagePaths», которая сопоставляет каждый путь с идентификатором, затем вы можете искать изображения с этим PathID и загружать данные из Столбец BLOB по мере необходимости.

XML-файлы также могут находиться в базе данных SQLite, что дает вам один «файл данных» для вашего приложения, который можно без проблем перемещать между Windows и OSX.Вы можете просто положиться на свой движок SQLite, который обеспечит необходимую вам производительность и совместимость.

То, как вы его оптимизируете, зависит от вашего использования, например, если вам часто нужно получать все изображения по определенному пути, то использование PathID (в виде целого числа для производительности) будет быстрым, но если вы показываете все изображения, которые начинаются с помощью «A» и просто покажите путь как свойство, тогда индекс в столбце ImageName будет более полезен.

Однако меня немного беспокоит то, что это звучит как преждевременная оптимизация, поскольку вам действительно нужно найти решение, которое работает «достаточно быстро», абстрагировать его механику, чтобы ваше приложение (или оба приложения, если у вас есть версии для Mac и ПК) использовало простой репозиторий или аналогичный, а затем вы можете изменить метод хранения/извлечения по своему желанию без каких-либо последствий для вашего приложения.

Проверять Надежная файловая система - Кажется, это то, что вам нужно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top