PHP从64位到32位的非序列化整数


PHP unserialized integer from 64-bit to 32-bit

我一直在尝试在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中编写了反序列化方法吗?有协议的细节吗?我可以用它为这些整数定制一个case

谢谢。

注意:不能访问原始数据,只能访问序列化后的结果

32位系统的最大整数为4294967296;$i = 20110510134021;可以工作,因为PHP将变量转换为double。

d代替i

$i = unserialize('d:20110510134021;');

如果您运行这个脚本,您将看到您正在运行的系统上变量的正确表示(d:在32位系统上,i:在64位系统上):

$int = 20110510134021;
var_dump(serialize($int));

一个简单的解决方案是,如果你知道64位机器上序列化的数据有可能在32位机器上被反序列化,那么在序列化之前将其强制转换为(double)。

然后它将被反序列化为双精度类型,每个整数比标准的每个整数4字节(32位)提供更多的位

一旦未序列化,就将该数字作为双精度体处理。在99%的情况下,这是一个很好的解决方案。对于一个非常大的数字,仍然有可能在32位机器上分配给数字的"实"部分的位数是不够的。我认为它是56位,所以最大整数仍然明显大于int类型的32位。

如何:

$serialized = 'i:20110510134021';
if (preg_match('/i':(['d]+)/', $serialized, $match))
{
    $unserialized = $match[1];
}