我一直在尝试在32位服务器上反序列化在64位服务器上序列化的对象。我已将我的问题隔离到对象中的整数。这是对问题的一个小小的再现。
在64位计算机上:
$i = serialize('20110510134021'); //i:20110510134021;
在32位计算机上:
$i = unserialize('i:20110510134021;');
给出错误
Notice: unserialize(): Error at offset 0 of 16 bytes
现在我明白这些序列化方法不应该用于跨系统数据传输。但是,我们只是尝试将数据迁移到另一个系统,而不是主动用于传输。这是一次性事情。
我认为这可能是由于整数溢出,但即使在32位服务器上,我也可以做类似的事情
$i = 20110510134021;
echo $i;
它会正常工作。我猜测PHP整数类型可以缩放到某种双重类型或类似的东西。但是当它反序列化时为什么不这样做呢?
如何反序列化这些对象?如果我不能,有没有办法将它们转换成其他东西?最后,有没有人在PHP本身编写反序列化方法?或者有协议的细节?我可以使用它并为这些整数设置一个自定义的案例。
感谢。
注意:我无法访问原始数据,只能访问序列化结果。
答案 0 :(得分:2)
32位系统的最大整数为4294967296
;
$i = 20110510134021;
有效,因为PHP将变量转换为double。
所以用i
d
$i = unserialize('d:20110510134021;');
如果运行此脚本,您将在正在运行的系统上看到变量的正确表示(d:在32位系统上,i:在64位系统上):
$int = 20110510134021;
var_dump(serialize($int));
答案 1 :(得分:1)
简单的解决方案是,如果您知道在32位机器上序列化的数据有可能在32位机器上被反序列化,那么在序列化之前将其转换为(double)。
然后它将被反序列化为double,为每个整数提供比每个整数(32位)标准4字节更多的位
一旦反序列化,只需使用该数字作为双精度。在99%的情况下,这是一个很好的解决方案。对于非常大的数字,在32位机器上分配给数字上的“真实”部分的位数仍然是不够的。我认为它是56位,所以最大整数仍然明显大于int类型的32位。
答案 2 :(得分:1)
怎么样:
$serialized = 'i:20110510134021';
if (preg_match('/i\:([\d]+)/', $serialized, $match))
{
$unserialized = $match[1];
}