Что такое переносимый способ записи структуры в файл в C?

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

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

Есть ли простой способ добиться этого?

Ответ 1

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

  • Упакуйте свои структуры (GCC __attribute__((packed)), MSVC #pragma pack). Это специфично для компилятора.
  • Убедитесь, что ваша целая сущность верна (htons, htonl). Это характерно для архитектуры.
  • Не используйте указатели для строк (используйте буферы символов).
  • Используйте C99 точные целочисленные размеры (uint32_t и т.д.).
  • Убедитесь, что код только компилирует, где CHAR_BIT равно 8, что является наиболее распространенным или иным образом обрабатывает преобразование символьных строк в поток 8-битных октетов. Существуют некоторые среды, где CHAR_BIT!= 8, но они, как правило, являются специализированным оборудованием.

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

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

Ответ 2

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

Ответ 3

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

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

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