Что поместить в заголовок файла двоичных данных - PullRequest
10 голосов
/ 06 января 2009

У меня есть симуляция, которая читает большие двоичные файлы данных, которые мы создаем (от 10 до 100 ГБ). Мы используем двоичный файл по соображениям скорости. Эти файлы зависят от системы и конвертируются из текстовых файлов в каждой системе, которую мы запускаем, поэтому меня не волнует переносимость. В настоящее время файлы представляют собой множество экземпляров структуры POD, написанной с помощью fwrite.

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

Ответы [ 12 ]

13 голосов
/ 06 января 2009

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

Я склонен хранить метаданные в структуре в конце файла, а не в начале. Это имеет два преимущества:

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

Простейший нижний колонтитул метаданных, который я использую, выглядит примерно так:

struct MetadataFooter{
  char[40] creatorVersion;
  char[40] creatorApplication;
  .. or whatever
} 

struct FileFooter
{
  int64 metadataFooterSize;  // = sizeof(MetadataFooter)
  char[10] magicString;   // a unique identifier for the format: maybe "MYFILEFMT"
};

После необработанных данных записываются нижний колонтитул метаданных и ТОГДА нижний колонтитул файла.

При чтении файла ищите до конца - sizeof (FileFooter). Прочитайте нижний колонтитул и проверьте magicString. Затем выполните поиск в соответствии с metadataFooterSize и прочитайте метаданные. В зависимости от размера нижнего колонтитула, содержащегося в файле, вы можете использовать значения по умолчанию для пропущенных полей.

Как указывает KeithB , вы можете даже использовать эту технику для хранения метаданных в виде строки XML, предоставляя преимущества как полностью расширяемых метаданных, так и компактности и скорости двоичных данных.

7 голосов
/ 06 января 2009

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

4 голосов
/ 06 января 2009

Для больших двоичных файлов, в дополнение к номеру версии, я стараюсь указывать количество записей и CRC, причина в том, что большие двоичные файлы гораздо более склонны к усечению и / или повреждению во времени или во время передачи, чем меньшие. Недавно, к своему ужасу, я обнаружил, что Windows не справляется с этим вообще, так как я использовал explorer для копирования около 2 ТБ из нескольких сотен файлов на подключенное устройство NAS и обнаружил, что 2-3 файла в каждой копии были повреждены (не полностью скопировано).

3 голосов
/ 06 января 2009

Если они такие большие, я бы зарезервировал здоровый кусок (64 КБ?) Пространства в начале файла и поместил туда метаданные в формате XML с последующим символом конца файла (Ctrl-Z). для DOS / Windows, Ctrl-D для Unix?). Таким образом, вы можете легко просматривать и анализировать метаданные с помощью широкого набора наборов инструментов для XML.

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

Одним из больших преимуществ HDF5, как упомянул @highpercomp, является то, что вам не нужно беспокоиться об изменениях в формате структуры, если у вас есть некоторое соглашение о том, какие имена и типы данных. Имена структур и типы данных хранятся в самом файле, так что вы можете передать свой код на C вдребезги, и это не имеет значения, вы все равно можете извлечь данные из файла HDF5. Это позволяет вам меньше беспокоиться о формате данных и больше о структуре данных, то есть меня не волнует последовательность байтов, это проблема HDF5, но мне все равно об именах полей и т. п.

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

3 голосов
/ 06 января 2009

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

2 голосов
/ 06 января 2009

@ rstevens сказал "идентификатор типа файла" ... хороший совет. Обычно это называется магическим числом и в файле не является термином злоупотребления (в отличие от кода, где это термин злоупотребления). По сути, это некоторое число - обычно не менее 4 байтов, и я обычно гарантирую, что хотя бы один из этих байтов не является ASCII - что вы можете использовать для проверки того, что файл того типа, который вы ожидаете, с низкой вероятностью путаницы , Вы также можете написать правило в / etc / magic (или локальный эквивалент), чтобы сообщить, что файлы, содержащие ваш магический номер, относятся к вашему специальному типу файлов.

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

1 голос
/ 19 апреля 2013

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

Приятно иметь функции для фиксированного размера заголовка (в начале):

  • Общее поле 'length' (включая заголовок).
  • Что-то вроде CRC32 (включая заголовок).

ОК, для переменной части XML или какого-то довольно расширяемого формата в заголовке хорошая идея, но действительно ли она нужна? У меня был большой опыт работы с ASN-кодированием ... в большинстве случаев его использование было перехвачено.

Что ж, возможно, у вас появится дополнительное понимание, когда вы посмотрите на такие вещи, как формат TPKT, который описан в RFC 2126 (глава 4.3).

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

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

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

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

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

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

Мы считаем, что это очень полезно (а) для получения информации, которую в противном случае нам пришлось бы просить клиента предоставить, и (б) для получения правильной информации - просто удивительно, как много клиентов сообщают, что они используют другую версию программного обеспечения на что претендуют данные!

0 голосов
/ 19 апреля 2013

Мой вариант объединяет подходы Родди и Джейсона С.

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

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

2) Используйте XML, YAML или JSON для метаданных. Это особенно полезно / безопасно, если метаданные добавляются в конце, потому что никто, читающий файл, не будет автоматически думать, что это все XML, потому что он начинается с XML.

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

...