Редактирование больших двоичных файлов - PullRequest
2 голосов
/ 27 октября 2011

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

Но проблема в том, как я могу редактировать эти файлы. Я думал о структуре файла, и это будет примерно так:

[DWORD] Number of files

     [DWORD]FileId
     [STRING]FileName
     [DWORD]FileSize
     [DWORD]FileIndex

[BYTES]All the files

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

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

Двоичный файл может иметь размер несколько сотен мегабайт, когда все файлы вставлены.

Так как другие программы делают это, например, игры используют эти большие файлы, а также много исправляют, есть ли какая-то хитрость для более быстрой вставки дополнительных байтов?

Ответы [ 7 ]

3 голосов
/ 27 октября 2011

Если это вообще возможно, я бы, вероятно, упаковал данные в zip-файл.Это не только очистит ваш каталог, но (особенно для текстовых файлов, которые вы упомянули) добавит сжатие, по сути, бесплатно.Существует также, конечно, немало существующих инструментов и библиотек для создания, проверки, изменения и т. Д. Zip-файла.

Использование zlib (для одного примера), большинстворабота выполняется для вас (например, как показано в minizip ).

3 голосов
/ 27 октября 2011

Нет "хитрости" для вставки байтов в середину файла.

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

Если вы имеете дело с нестатическими данными, я бы не советовал делать это, если вам абсолютно не нужно. Я видел, как блестящие инженеры-программисты потратили немало времени, чтобы написать разумную реализацию этого.

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

1 голос
/ 27 октября 2011

Хитрость заключается в том, чтобы делать исправления путем перезаписи данных.В противном случае существуют системы для управления большими объемами данных, например, базы данных.

Вы можете создать файл базы данных, который будет сопровождать вашу программу, и хранить все ваши данные там, а не в файлах.Вы даже можете встроить код базы данных в свое приложение, например, с помощью SQLite или использовать внешние БД, такие как Sql Server, Oracle SQL или MySql.

То, что вы описываете, в основномреализовать свою собственную файловую систему.Сделать это эффективно - сложная и очень сложная задача.

1 голос
/ 27 октября 2011

Вы можете рассматривать программу упаковки и редактирования как пользовательский распределитель памяти:

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

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

И то и другое добавит пакету немного накладных расходов, но оставление пробелов на самом деле является единственной альтернативой переписыванию всего на каждой вставке.

0 голосов
/ 27 октября 2011

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

0 голосов
/ 27 октября 2011

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

Несколько примеров, которые приходят на ум:

  • Файл Word .docx действительно является zip (переименуйте его в .zip, и вы можете открыть его - в нем есть целые папкив нем)
  • .xap-файл, используемый пакетами Silverlight, является еще одним.
0 голосов
/ 27 октября 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...