Сохраняйте и загружайте данные с использованием ANSI C на любой платформе - PullRequest
1 голос
/ 11 июня 2011

Скажем, у меня есть 1 миллион структур, каждая из которых содержит целые, двойные, строковые и другие структуры, что-то вроде:

struct s1 {
    int f1;
    long f2;
    char* f3;
};

struct s2 {
    struct s1* f1;
    double f2;
};

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

Ответы [ 3 ]

3 голосов
/ 11 июня 2011

Запишите их как текст ascii, XML или какой-либо подобный недвоичный формат.

2 голосов
/ 11 июня 2011

"платформы, отличные от той, на которой исполняемый файл был скомпилирован"

Насколько отличается от того, на котором был скомпилирован исполняемый файл? Вам нужно поддерживать платформы, которые используют плавающие не IEEE? Платформы, которые используют символы не ASCII? Платформы, которые используют не 8-битные байты?

Если вы настаиваете на двоичном коде и настаиваете на том, чтобы сделать это самостоятельно, вероятно, лучше всего определить, что в формате хранения int и long будут храниться в виде последовательности из 4 байтов с прямым порядком байтов (или big-endian, но выберите один и придерживайтесь его независимо от платформы), содержащий ровно 8 значащих бит на байт. double также будет двойным IEEE. Указатели вводят целый мир вреда, формат хранения должен прикреплять уникальный идентификатор к каждому экземпляру s1, а затем указатель на s1 может быть сохранен как значение идентификатора и может быть найден как часть десериализации.

Различные платформы могут затем решить, какие типы они хотят использовать для каждого из типов хранилищ (так, например, если int - это только 16 бит на данной платформе, ей просто нужно будет использовать long для обоих * Типы 1014 * и long. По этой причине вы должны указывать для них псевдонимы, относящиеся к конкретному домену). Помните, что невозможно избежать потери точности в двойных значениях при преобразовании в несовместимые представления и из них, поскольку они могут иметь разное количество значащих битов.

Для текста платформы без ASCII должны будут включать код для сериализации своего собственного текстового формата в ASCII и десериализации ASCII в нативный текст. Строго говоря, вам также следует избегать использования любых символов в тексте, которых нет в базовом наборе символов C, поскольку они могут вообще не быть отображаемыми на цели. Вы можете принять аналогичное решение, готовы ли вы рассчитывать на целевые платформы для поддержки Unicode каким-либо образом - если это так, то UTF-8 является разумным форматом обмена для текста.

Наконец, для каждой структуры на каждой платформе вы можете:

  1. написать (или, возможно, автоматически сгенерировать) код для его сериализации и код для его десериализации, или:
  2. сделайте себя предметно-ориентированным языком для определения структур и синтаксическим анализатором / интерпретатором, который сериализует и десериализует в соответствии с этим определением.

Звучит для меня как большая работа, чтобы сделать что-то, что было сделано раньше.

0 голосов
/ 11 июня 2011

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

*, пока вы не начнете проникать в локали.

...