我遇到的麻烦是:不是所有的变量(例如int或复合对象之类的原始变量)都已经由字节序列表示了吗?
对,他们是。这里的问题是这些字节的布局。一个简单的int
可以是2、4或8位长。它可以是大端或小端。它可以是无符号的,也可以用1的补码进行签名,甚至可以使用诸如负数之类的一些超级奇异位编码。
如果只是int
从内存中转储二进制文件,并将其称为“序列化”,则必须附加几乎整个计算机,操作系统和程序,才能对其进行反序列化。或者至少是它们的精确描述。
那么,什么使序列化成为如此深刻的话题呢?要序列化一个变量,我们不能只将这些字节存储在内存中,然后将它们写入文件吗?我错过了什么错综复杂的事情?
一个简单对象的序列化几乎是根据一些规则将其记录下来的。这些规则很多,但并不总是很明显。例如,xs:integer
用XML编写的以10为基数。不是以16为基数,不是以9为基数,而是10。这不是一个隐藏的假设,而是一条实际规则。这样的规则使序列化成为序列化。因为几乎没有关于程序在内存中的位布局的规则。
那只是冰山一角。让我们以这些最简单的原语序列为例:C struct
。你可能会认为
struct {
short width;
short height;
long count;
}
在给定的计算机+ OS上有定义的内存布局?好吧,事实并非如此。根据当前#pragma pack
设置,编译器将填充这些字段。在32位编译的默认设置下,两者都shorts
将填充为4个字节,因此它们struct
实际上将在内存中具有3个4字节的字段。因此,现在,您不仅需要指定short
16位长,而且是一个整数,以1的补码负,大或小尾数表示。您还必须写下编译程序时使用的结构打包设置。
这几乎就是序列化的意义:制定一套规则,并遵守这些规则。
然后可以扩展这些规则,以接受甚至更复杂的结构(如可变长度列表或非线性数据),添加诸如人类可读性,版本控制,向后兼容性和错误纠正等功能,但是即使编写单个代码int
也已经足够复杂,如果您只希望确保您能够可靠地读回它。