WXF 格式说明
WXF 是一种二进制格式,忠实地把 Wolfram 语言表达式序列化成适于外部存储或可与其他程序交换的形式. WXF 可使用许多编程语言中的低级原始类型进行诠释,使之可在其他编程语言中读取或编写 Wolfram 语言表达式.
Wolfram 语言表达式和其序列化格式间转换的基本函数是 BinarySerialize 和 BinaryDeserialize. 对 WXF 数据的文件的读取和编写的支持也内置于 Export 和 Import.
BinarySerialize[expr] | 给出 WXF 格式中任何表达式 expr 的二进制表示 |
BinaryDeserialize[bytearray] | 从 WXF 格式中的二进制表示恢复一个表达式 |
Import[file,"WXF"] | 导入一个 WXF 文件并返回一个表达式 |
Export[file,expr,"WXF"] | 序列化任意表达式并存为一个 WXF 文件 |
ImportByteArray[ba,"WXF"] | 导入数据并返回一个表达式 |
ExportByteArray[expr,"WXF"] |
在 Wolfram 语言中有很多种方式序列化和反序列化 WXF.
基本结构
WXF 格式中的数据总是包含纯 ASCII 标头紧跟着一个字节字符串. 标头指明如何解码字节并用冒号分隔表示成分序列的字节字符串.
字节值 |
字符表示 (ISO8859-1)
| 成分类型 |
102 | "f" | 函数 |
67 | "C" | 带符号 8 位整数 |
106 | "j" | 带符号 16 位整数 |
105 | "i" | 带符号 32 位整数 |
76 | "L" | 带符号 64 位整数 |
114 | "r" | IEEE 双精度实数 |
83 | "S" | 字符串 |
66 | "B" | 二进制字符串 |
115 | "s" | 符号 |
73 | "I" | 大整数 |
82 | "R" | 大实数 |
193 | "Á" | 打包数组 |
194 | "Â" | 数值数组 |
65 | "A" | 关联 |
58 | ":" | 关联中的延迟规则 |
45 | "-" | 关联中的规则 |
基本范例
为 Range[10] 的序列化格式给出字节:
多成分的范例
第二个范例是三个元素的列表. 该列表表示长度为 3 的函数,其中,标头 List 紧跟 3 个成分. 第一个成分引入了用于表示紧密格式的整数格式,使用一个令牌和一个 "Integer8". 最后部分显示一个 ByteArray 的表示:
给出 {1,-1,ByteArray[{1,2,3}]} 序列化格式的字节:
标头是四个字节的符号,即 List:
更多关于标头
标头是变长度的纯 ASCII 字符串,由字符 ":" 分割. 对于 WXF 的当前版本 (1.0),标头的第一个字节是字符 "8"(例如,字节值 56). 当二进制序列化被 zip 压缩,这会通过字符 "C" 在标头指明. 标头永远不会被压缩;压缩只适用于接下来的字节字符串.
长度编码 (Varint)
WXF 类型有三类:
- 带有子成分的变式类型,例如,一般表达式(函数的令牌类型 "f")或 Association.
在 WXF 中,所有表示长度或尺寸的整数均使用变式 (varint) 方法序列化. 变式是自我表明的变量长度格式,其中,更小的整数需要更少的字节. 除最后一个字节外的每个字节都设置了最高有效位 (MSB). MSB 指示流的后续字节是否也是变式的一部分,作为延续标记. 每个字节的低 7 位存储整数的二进制表示,最低有效组首先存储.
字符串、符号和非机器数
使用同样的格式表示字符串、符号和非机器数. 第一个字节是一个令牌,然后字节数编码成 varint 格式,接下来是 Unicode 字符的字符串,对应于表达式的字符串 InputForm. 非机器数可以是任意精度的实数或整数,其需要比 $SystemWordLength 位数更长的表示.
原子类型 | 令牌 | 表示 |
String | "S" | Unicode 字符序列 |
Symbol | "s" | 符号完全符合的名称,指定上下文,除了 System` 符号 |
Arbitrary-precision reals | "R" | 数字表示指定尾数和最终的精度和指数 |
Big integers | "I" | 数字字符串 |
基于 InputForm 的类型.
下两个字节是 varint 编码的 500,出现在之前的范例中:
机器整数序列化
令牌 | 定义 | 类型大小 |
"C" | signed 8-bit integer | |
"j" | signed 16-bit integer | |
"i" | signed 32-bit integer | |
"L" | signed 64-bit integer |
机器实数序列化
机器精度复数是作为两个机器精度实数的函数序列化的. 下图高亮 Complex 标头以及紧跟着的两个实数值:
标头后的第一个字节是长度为 2 的函数,其中标头为 Complex:
函数序列化
WXF 中的函数由字符 "f" 表示,紧跟着 varint 格式的表达式长度. 对于标头,元素数目等于长度加 1. 标头和成分是任意序列化的表达式. 另外,标头也可以是函数:Select[OddQ][{1,2,3}] 是长度为 1 的函数,标头为 Select[OddQ],它本身是标头为 Select 且长度为 1 的函数.
序列化一个表达式,使用 Unevaluated 阻止它被计算:
关联序列化
首元素是长度为 2 的函数,标头为 Rule:
第二个元素也是长度为 2 的函数,但是它的标头是 RuleDelayed:
序列化长度大致是字符串 FullForm 的大小:
二进制字符串
数值数组
整数值 | 16 进制表示 | 数组类型 |
0 | 0016 | 8 位带符号整数数组 |
1 | 0116 | 16 位带符号整数数组 |
2 | 0216 | 32 位带符号整数数组 |
3 | 0316 | 64 位带符号整数数组(只适于 64 位系统) |
34 | 2216 | IEEE 单精度实数数组(float) |
35 | 2316 |
IEEE 双精度实数数组 (double)
|
51 | 3316 | IEEE 单精度复数数组 |
52 | 3416 | IEEE 双精度复数数组 |
整数值 | 16 进制表示 | 数组类型 |
0 | 0016 | 8 位带符号整数数组 |
16 | 1016 | 8 位无符号整数数组 |
1 | 0116 | 16 位带符号整数数组 |
17 | 1116 | 16 位无符号整数数组 |
2 | 0216 | 32 位带符号整数数组 |
18 | 1216 | 32 位无符号整数数组 |
3 | 0316 | 64 位带符号整数数组 |
19 | 1316 | 64 位无符号整数数组 |
34 | 2216 |
IEEE 单精度实数数组 (float)
|
35 | 2316 |
IEEE 双精度实数数组 (double)
|
50 | 3316 | IEEE 单精度复数数组 |
51 | 3416 | IEEE 双精度复数数组 |
打包数组支持的整数范围随系统单词长度,$SystemWordLength 而变化,在 32 位系统从 -231+1 到 231-1,在 64 位系统,从 -263+1 到 263-1. 实数的打包数组不能存储 IEEE 除了 NaN 和 inf. 这些限制不适用于数值数组.
下面的交互性插图显示了上面矩阵压缩前的序列化. 元素序列显著不同,因为它包含带有标头 List 的嵌套函数. 内部列表有三部分对应整数值. 值得注意的是整数值的二进制表示类似于压缩数组的情况(小端带符号 16 位 整数) .