1

我一直试图在 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 整数类型可以扩展到一些 double 类型或类似的东西。但是为什么它在反序列化时不这样做呢?

如何反序列化这些对象?如果我不能,有什么办法可以将它们转换成别的东西?最后,有没有人在 PHP 本身中编写了反序列化方法?或者有关于协议的详细信息?我可以使用它并为这些整数提供一个自定义案例。

谢谢。

注意:我无法访问原始数据,只能访问序列化结果。

4

3 回答 3

2

32 位系统上的最大整数是4294967296; $i = 20110510134021;有效,因为 PHP 将变量转换为双精度。

所以替换id

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

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

$int = 20110510134021;
var_dump(serialize($int));
于 2011-10-26T15:00:46.357 回答
1

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

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

一旦反序列化,只需将该数字用作双精度数。在 99% 的情况下,这是一个很好的解决方案。对于非常大的数字,在 32 位机器上分配给数字上的“真实”部分的位数仍然有可能是双倍的,这还不够。我认为它是 56 位,因此最大整数仍然明显大于 int 类型的 32 位。

于 2011-10-26T14:56:15.173 回答
1

怎么样:

$serialized = 'i:20110510134021';

if (preg_match('/i\:([\d]+)/', $serialized, $match))
{
    $unserialized = $match[1];
}
于 2011-10-26T14:59:05.140 回答