R对象的序列化版本被load/save使用。
在底层,则被.saveRDS/.readRDS 和
serialize/unserialize 使用。
这取决于将被序列化的对象(文件,连接,原味向量)以及市序列化
一个对象还是一个对象集合(通常是一个工作空间)。
save写一个信息头在文件的开端(一个以LF结尾的行)
注明格式信息,而低层次的版本不会这样做。
R 在2001年12月份的R 1.4.0后就使用一样的序列化格式。
load 仍然支持早期信息的读取,但在这里我们不会讨论。
(这些格式的文件在包的data目录下面仍然可以看到)
当前序列化的格式被称为 `版本 2',并且从
R 1.4.0开始向后兼容。比如,支持附加的
SEXPTYPE。
save()首先创建一个被保存对象的加有便签的成对列表,
然后保存这个对象并且在前面加单行的信息头(二进制保存
的时候通常加RDX2\n)。
load() 读取信息头,对单个对象进行去序列化(一个成对列表
或者一个向量列表),在适当的环境中能分配列表的元素。
R里面的序列化需要考虑到对象也可能含有对环境的引用(references), 而这些引用随后可能会附上环境等。 (作为包或者命名空间的环境以名字保存。) 此外,还有在拷贝上没有重复但在去序列化时保持共享的 `引用对象'(reference object)。 这些是弱引用,其它外部指针和环境都和包 ,命名空间和全局环境相关。 这些通过哈希表来操作。在第一个之后的引用以 通过表格条目建立索引且以参考符号(reference marker) 的方式写出。
序列化首先写一个信息头表明格式(
一个XDR格式的二进制保存通常是X\n)
以及格式和两个R版本的版本号(以整数的方式)。
(去序列化需要解释这两个版本,因为
生成这个文件的R版本跟随着可以
读这种格式的最小R版本。)
序列化然后用文件src/main/serialize.c中的
函数WriteItem递归写出对象。
一些对象被写出时就像它们是SEXPTYPE:
这种假SEXPTYPE包括了R_NilValue, R_EmptyEnv,
R_BaseEnv, R_GlobalEnv, R_UnboundValue,
R_MissingArg 和 R_BaseNamespace。
对所有除NILSXP,SYMSXP 和
ENVSXP 外的 SEXPTYPE,序列化
从二进制位0:7 1的一个整数开始,
随后是对象二进制位,两个二进制位表明是否有一些属性以及是否有标签(成对列表类型),
一个没有用到的二进制位,然后是12:27的gp 字段
2
成对列表类似的对象写入它们的属性(如果有),
标签(如果有),CAR,然后CDR(使用尾部递归):
其它对象在它们自身后面写入属性。
原子性向量对象在他们数据后面写入它们的长度:
泛型向量-列表对象在对每个元素调用WriteItem后写入长度。
对于 CHARSXP 的特例 NA_STRING,
写入它的长度 -1 但没有数据。
环境从多个角度处理:如前所示,一些环境当作
特殊的假-SEXPTYPE写入。包和命名空间
的环境就是以假-SEXPTYPE写入,随后是
它们的名字。。
`常规'环境以ENVSXP写出,并且包括
一个整数表明环境是否被锁住,随后是
外围(enclosure),框架,标签和属性。