在任何平台上使用ANSI C保存和加载数据

时间:2011-06-11 17:31:17

标签: c serialization deserialization storage

假设我有100万个结构,每个包含整数,双精度,字符串和其他结构,如:

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

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

如何将这些文件以二进制格式保存到文件中,然后在不同于编译可执行文件的平台上查找并从该文件加载它们,而不必担心字节顺序,浮点表示和其他特定于平台的陷阱?

优先选择二进制格式的原因主要是生成文件的大小。如果单独的整数看起来像“32435”并且我有数百万个,那么每个整数额外的3个字节会为文件增加相当大的大小。

3 个答案:

答案 0 :(得分:3)

将它们写成ascii文本,XML或一些类似的非二进制格式。

答案 1 :(得分:2)

"平台不同于可执行文件编译的平台"

与编译可执行文件的方式有何不同?您是否需要支持使用非IEEE浮动的平台?使用非ASCII字符的平台?使用非8位字节的平台?

如果你坚持使用二进制文件,并坚持自己做,可能最好的办法是定义存储格式,intlong将每个存储为4字节的序列,little-endian(或big-endian,但选择一个并坚持使用它,无论平台如何),每个字节包含恰好8个有效位。 double同样是IEEE双倍。指针引入了整个受伤的世界,存储格式必须为s1的每个实例附加唯一标识符,然后指向s1的指针可以存储为id值,并查找为反序列化。

然后,不同的平台可以决定他们想要为每种存储类型使用哪种类型(例如,如果在给定平台上int只有16位,则只需使用long适用于int long类型。因此,您应该为它们提供特定于域的假名)。请注意,在转换为不兼容的表示时,不可能避免双值的精度损失,因为它们可能没有相同数量的有效位。

对于文本,非ASCII平台必须包含将自己的文本格式序列化为ASCII并将ASCII反序列化为本机文本的代码。严格地说,您还应该避免在C基本字符集中使用不在文本中的任何字符,因为它们可能在目标上根本不可表示。您是否愿意依靠目标平台以某种方式支持Unicode,您可以做出类似的决定 - 如果是这样,则UTF-8是文本的合理交换格式。

最后,对于每个平台上的每个结构,您可以:

  1. 编写(或者可能是自动生成)代码来序列化它,并编写代码来反序列化它,或者:
  2. 使自己成为定义结构的特定于域的语言,以及根据该定义进行序列化和反序列化的解析器/解释器。
  3. 但是,对我来说,做一些以前做过的事情听起来很不错。

答案 2 :(得分:0)

如果您想避免您所描述的头痛,请不要使用二进制文件。使用text,通用*格式。

*直到你开始进入区域设置。