用于结构化数据的 fread 和 fwrite 的替代方案

5

这本书 Beginning Linux Programming (第三版) 中写道:

"请注意,不建议使用 fread 和 fwrite 处理结构化数据。问题的一部分在于,用 fwrite 写入的文件在不同机器之间可能是不可移植的。"

这句话具体意思是什么?如果我想编写一个可移植的结构化数据读写程序,应该使用哪些调用?直接使用系统调用吗?

3个回答

3
这本书明智地警告我们不要直接将一个字节块从文件中读入数据结构。这样做的问题是,数据结构中的各个元素之间可能存在未命名的填充字节,这些字节的数量和位置完全取决于实现方式。您仍然可以使用fread和fwrite调用从文件中读取和写入数据,但应该逐个读取或写入每个数据结构元素,而不是一次性读取或写入整个结构体。还有其他可移植性问题需要注意。例如,各种数字类型具有实现相关的大小。为了可移植性,您可以使用stdint.h头文件中定义的类型。浮点数和无符号整数表示也可能存在差异,但大多数系统和文件格式现在使用IEEE 754和二进制补码表示,因此与这些类型的兼容性问题要少得多。只需确保您知道自己的规格说明即可。

非常感谢。据我所知,数据结构始终是依赖于实现的填充方式,因此似乎与fread或fwrite无关。在谈论特定调用(如fread或fwrite)时强调这个问题是否有些奇怪? - WuFa
1
@forest:正是因为fread/fwrite不知道填充(padding)的存在,所以使用它们可能会失败。例如,给定struct A { int i; char c; };,你需要两个fread调用(一个用于i,另一个用于c),而不是一个(用于整个结构体)。关于可移植整数类型的要点在于,你不依赖于int使用的特定位数(这可以因平台甚至编译器设置而异)。 - Roger Pate

1

数据序列化是你感兴趣的话题。

它涉及变量的大小,编码(字符串可能是utf-8、utf16等),以及字节序(大端、小端)。

为了实现可移植性解决方案,我建议你看看Google Protocol Buffers和Thrift


0
如果数据的可移植性是您关心的问题,您应该研究序列化技术和库,特别是s11n、JSON、YAML、XDR、ASN1、Jansson、XML等。请考虑一下您的数据和应用程序在未来几年内的情况。
文本表示通常比二进制表示更加灵活。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接