Упакуйте файлы с помощью c, чтобы их можно было распаковать в исходные файлы - PullRequest
0 голосов
/ 06 марта 2011

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

Ответы [ 3 ]

1 голос
/ 06 марта 2011

Я полагаю, что объяснение желания написать собственную реализацию может быть любопытным.

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

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

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

  1. Записать в архив завершенную '\ 0' C-строку, в которой указан упакованный файл.
  2. Записать в архив off64_tкоторый дает длину в байтах упакованного файла.
  3. Запись в архив фактических байтов (если есть) упакованного файла.
  4. (Необязательно) Запись в архив контрольной суммыили CRC упакованного файла.

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

Наконец, когда файлов не осталось, напишите пустую C-строку, ноль символа.

Процесс распаковки:

  1. Считать C-строку, оканчивающуюся на \ 0, с именем этого упакованного файла.
  2. Еслиимя пустое, подтвердите, что мы прочитали весь архив, затем выйдите.
  3. Считайте off64_t, который дает длину упакованного файла.
  4. Считайте столько байтов, сколько длины упакованного файла изархив и запись в только что созданный распакованный файл.

Снова повторяйте эти шаги до тех пор, пока шаг (2) не завершит программу.

Эта схема, в которой имена файлов чередуются с данными файлов, является работоспособной.У него есть некоторые недостатки.Основная проблема заключается в том, что структура данных не предназначена для произвольного доступа.Чтобы получить информацию о файле в «середине» архива, необходима программа для обработки предыдущих файлов.Программа может вызвать lseek_64, чтобы пропустить чтение данных программы, которые не нужны, но процессор должен прочитать хотя бы каждое имя файла и каждую длину файла.Длина файла необходима, чтобы пропустить данные файла.Имя файла, как я расположил данные, должно быть прочитано, чтобы определить длину файла.

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

Лучшим подходом может быть запись «блока» индексных данных в начало файла.Эта структура данных может выглядеть примерно так:

  1. Размер первого файла в архиве.
  2. Имя первого файла в архиве.
  3. позиция в байтах внутри этого архива, где «первый файл» может находиться как непрерывный блок байтов.
  4. размер второго файла в архиве ...

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

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

Файловая структура может становиться все более и более сложной, чтобы удовлетворить все эти различные потребности.Например, индекс может быть спроектирован так, чтобы он всегда выделялся из того, что файловая система считает «страницей» (объем, который ОС считывает или записывает с диска как гранулу минимального размера), и если индекс долженрастут, отдельные "индексные страницы" объединены в цепочку данными о положении файла, ведущими от одной индексной страницы к другой.(Как связанный список, но на диске.) Сложность может продолжаться и продолжаться.

1 голос
/ 06 марта 2011

Быстрое решение - использовать внешнюю библиотеку, такую ​​как zLib (пример использования: http://zlib.net/zlib_how.html), и использовать ее для сжатия.

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

0 голосов
/ 27 июля 2012

Я написал программу, похожую на tar, пару дней назад, здесь моя реализация (надеюсь, вы можете получить некоторые идеи): Каждый файл хранится в файловом архиве с «заголовком», который выглядит так:

<file-type,file-path,file-size,file-mode>

в типе файла я использовал 0 для файлов и 1 для каталогов (таким образом, вы можете воссоздать дерево каталогов) Например, заголовок файла с именем foo.txt размером 245 байт в режиме 0755 (в unixсм. chmod) будет выглядеть так:

<0,foo.txt,245,0755>
here the file contents

, таким образом, первый символ файлового архива всегда равен <, затем вы анализируете список, разделенный запятыми (первая возможная ошибка), и извлекаете файлтип, путь, размер (который вы будете использовать для чтения следующих <em>размеров байт из архива - чтобы избежать «ошибки специального символа», указанной Хитом Ханникуттом) и режим файла (давайтескажем, у вас есть бинарный файл, и вы хотите, чтобы он также был исполняемым при извлечении, вам нужно выполнить chmod в исходном файловом режиме).

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

Для записи и чтения файлов в C смотрите fgetc и fputc из stdio.h Чтобы получить информацию о файлах, chmod и каталоги, смотрите stat и chmod из sys/stat.h и ftw из ftw.h (возможно, только linux / unix, потому что это системный вызов).

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

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