Создать заголовок файла (метаданные файла) в C - PullRequest
4 голосов
/ 09 марта 2012

Заголовок файла содержит все данные о файле - метаданные.Я хочу создать пустой файл с метаданными, затем я хочу добавить другое содержимое файла в этот пустой файл и мне нужно изменить (изменить) метаданные.Есть ли в C библиотека для создания заголовка файла?Как читать / писать заголовок файла в C?

metadata =
{
file_name;
file_size;
file_type;
file_name_size;
total_files;
}

Ответы [ 3 ]

5 голосов
/ 09 марта 2012

Вероятно, существует ряд библиотек, которые обрабатывают определенные форматы файлов, например, варианты tar, но не те, которые будут адаптированы к вашему конкретному формату заголовка.

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

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

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

Обратите внимание, что вы должны поместить размер (длину) имени файла перед фактическим именем файла в данных на диске.Затем вы можете прочитать, насколько велико имя, выделить нужное место и прочитать правильный объем данных.Размещение длины имени файла после имени файла на самом деле не очень помогает.

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

Вам также следует рассмотреть возможность использования«магическое число», позволяющее идентифицировать, что файл содержит правильные данные.'Number' может быть строкой ASCII, например !<arch>\n, используемой в некоторых версиях заголовков ar.Или %PDF-1.3\n, используемый в начале файла PDF.Сказав это, tar в значительной степени уходит без магического числа в первых байтах, но это необычный дизайн в наши дни.Программа file много знает о магических числах.Его данные иногда можно найти в файле - например, в /usr/share/file для Mac OS X.


Не могли бы вы объяснить каким-нибудь примером?

Один формат файла, с которым я имею дело, предназначен для сообщений, обозначаемых 32-битным (подписанным) числом, с переменной длиной сообщений и, следовательно, смещениями.Файл написан в платформо-нейтральном, но двоичном формате.Числа пишутся с прямым порядком байтов, сначала MSB.Номера сообщений в настоящее время ограничены диапазоном ± 99 999 (так что в системе в целом может поместиться чуть менее 200 000 сообщений).

Заголовок файла содержит:

  • 2-байтовое (без знака) магическое число
  • 2-байтовое (без знака) количество сообщений, содержащихся в файле, N

За ним следует N записей, каждаяиз которых описывает сообщение:

  • 4-байтовый (подписанный) номер сообщения
  • 2-байтовая (без знака) длина сообщения
  • 4-байтовое (без знака) смещениек началу сообщения

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

После N записей следуют фактические тексты сообщений, каждый из которых состоит из соответствующего количества байтов, идентифицированных соответствующей записью, плюс ASCII NUL '\0' байт.

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

Чтение номера сообщения M достаточно просто.Вы делаете бинарный поиск по N записям, чтобы найти запись для M. Если ее там нет, пусть будет так - это ошибка.Если он есть, вы знаете, где его найти в файле и как долго он находится.

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


Если описанный выше формат был преобразован в текстовый формат, то он, вероятно, будет иметь 8 байтов (скажем)зарезервировано для магического числа (которое может быть 7-буквенной строкой, за которой следует новая строка), а 6 байтов зарезервировано для количества сообщений (5 цифр плюс символ новой строки).Каждая из записей сообщения может быть зарезервирована 6 байтами для номера сообщения (± 99,999 для номера), плюс пробел, плюс 4 байта для длины (максимум, 8 КБ) плюс пробел, а также смещение в 8 байтов (7 цифр)плюс перевод строки).

MAGICNO
12345
-99999 8000 0000000
-90210   38 0008000
...

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

Вы можетеесть бесконечные вариации на эту тему.

1 голос
/ 09 марта 2012

int stat(const char *path, struct stat *buf); может предоставить вам следующую информацию о файле

struct stat {
    dev_t     st_dev;     /* ID of device containing file */
    ino_t     st_ino;     /* inode number */
    mode_t    st_mode;    /* protection */
    nlink_t   st_nlink;   /* number of hard links */
    uid_t     st_uid;     /* user ID of owner */
    gid_t     st_gid;     /* group ID of owner */
    dev_t     st_rdev;    /* device ID (if special file) */
    off_t     st_size;    /* total size, in bytes */
    blksize_t st_blksize; /* blocksize for file system I/O */
    blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
    time_t    st_atime;   /* time of last access */
    time_t    st_mtime;   /* time of last modification */
    time_t    st_ctime;   /* time of last status change */
};

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

1 голос
/ 09 марта 2012

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

struct metadata=
{
file_name;
file_size;
file_type;
file_name_size;
total_files;
} data;

Затем вы можете сохранить с помощью команды fwrite и прочитать с помощью освобожденной команды, сначала открыв файл и:

fwrite(data,sizeof(metadata),1,FILE_POINTER);

fread(data, sizeof(metadata), 1, FILE_POINTER);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...