Дизайн: редактор больших архивных файлов, отображение файлов - PullRequest
2 голосов
/ 12 октября 2008

Я пишу редактор для больших архивных файлов (см. Ниже) объемом 4 ГБ +, в нативном и управляемом C ++.

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

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

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

уточнить:

  • Это не текстовый файл, я пишу определенный двоичный файл формат файла архива . Под этим я подразумеваю большой файл, который содержит много других, в каталогах. Пользовательские архивные файлы очень часто используются в игре по ряду причин. С моим форматом я нацеливаюсь на похожую (но несколько более простую) структуру, как с форматом GCF Valve Software - я бы использовал формат GCF как есть, но, к сожалению, редактора для этого формата не существует, хотя есть много отличных реализаций для их чтения, таких как HLLib .

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

  • «Сопоставление файлов», о котором говорилось здесь, является специфической техникой на платформе Windows, которая обеспечивает прямой доступ к большому файлу посредством создания «представлений» к его частям, см. Здесь: http://msdn.microsoft.com/en-us/library/aa366556(VS.85).aspx - Этот метод обеспечивает минимальную задержку и использование памяти, и это не составляет труда для доступа к любым большим файлам. Так что не означает чтение всего 4 ГБ файла в память, это как раз наоборот.

Ответы [ 6 ]

2 голосов
/ 12 октября 2008

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

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

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

2 голосов
/ 12 октября 2008

Что вы подразумеваете под «редактором программного обеспечения»? Если это текстовый файл, пробовали ли вы уже существующие редакторы производственного качества, прежде чем писать свои собственные? Если это файл, хранящий двоичные данные, рассматривали ли вы возможность использования СУБД и манипулирования ее содержимым с помощью операторов SQL?

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

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

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

Для монопольного доступа к файлам используйте блокировку файлов вашей операционной системы или реализуйте блокировку на уровне приложения (если только ваш редактор будет касаться этих файлов). В зависимости от mmap для монопольного доступа ограничиваются ваши варианты реализации.

1 голос
/ 31 января 2009

У картографирования есть основная проблема с файлом в удаленной системе.

В старые добрые времена DOS существовал замечательный редактор Norton Editor (ne.com .. это имя файла, а не веб-сайт). Может загружать файлы любого размера (речь идет о 640 КБ ОЗУ и 20 ГБ жестких дисков, если есть).

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

ИМХО, такой подход следует использовать.

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

1 голос
/ 13 октября 2008

Что я делаю, так это закрываю дескриптор (ы) представления и дескриптор FileMapping, устанавливаю размер файла, затем снова открываю дескрипторы отображения / просмотра.

// Open memory mapped file    
HANDLE FileHandle = ::CreateFileW(file_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
size_t Size = ::GetFileSize(FileHandle, 0);
HANDLE MappingHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READWRITE, 0, Size, NULL);
void* ViewHandle = ::MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, Size);

...

// increase size of file
UnmapViewOfFile(ViewHandle);
CloseHandle(MappingHandle);

Size += 1024;


LARGE_INTEGER offset;
offset.QuadPart = Size;

LARGE_INTEGER newpos;
SetFilePointerEx(FileHandle, offset, &newpos, FILE_BEGIN);
SetEndOfFile(FileHandle);

MappingHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READWRITE, 0, Size, NULL);
ViewHandle = ::MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, Size);

Приведенный выше код не проверяет ошибки и не обрабатывает 64-битные размеры, но это не сложно исправить.

1 голос
/ 12 октября 2008

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

0 голосов
/ 20 апреля 2009

Я бы собрал большой файл из кусочков во время сборки. Ваш редактор работает с обычными плоскими файлами в обычной файловой системе (с подкаталогами и т. Д., В зависимости от обстоятельств). Затем у вас есть шаг компиляции, который объединяет все эти части в ваш архив формат файла.

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