我一直在尝试在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本身写了一个反序列化方法?或者有关于协议的详细信息?我可以使用它,并为这些整数自定义大小写。
谢谢。
注意:我不能访问原始数据,只能访问序列化后的结果。
发布于 2011-10-26 23:00:46
32位系统上的最大整数是4294967296
;$i = 20110510134021;
之所以能工作,是因为PHP将变量转换为double。
所以用d
替换i
$i = unserialize('d:20110510134021;');
如果您运行此脚本,您将看到正在运行的系统上变量的正确表示(d:在32位系统上,i:在64位系统上):
$int = 20110510134021;
var_dump(serialize($int));
发布于 2011-10-26 22:56:15
简单的解决方案是,如果您知道在64位上序列化的数据有可能在32位机器上被反序列化,那么在序列化之前将其强制转换为(double)。
然后,它将被反序列化为双精度型,从而为每个整数提供比标准4字节/整数(32位)更多的位数
一旦取消序列化,只需将该数字用作双精度数即可。在99%的情况下,这是一个很好的解决方案。对于一个非常大的数字,仍然存在这样的可能性:在32位机器上,分配给数字上的“实数”部分的位数为双精度是不够的。我认为它是56位,所以最大整数仍然比int类型的32位大得多。
发布于 2011-10-26 22:59:05
这样如何:
$serialized = 'i:20110510134021';
if (preg_match('/i\:([\d]+)/', $serialized, $match))
{
$unserialized = $match[1];
}
https://stackoverflow.com/questions/7904355
复制相似问题