【问题标题】:Is PHP serialize function compatible UTF-8?PHP 序列化函数是否兼容 UTF-8?
【发布时间】:2010-03-30 07:43:46
【问题描述】:

我想将一个网站从 ISO 迁移到 UTF-8

我在数据库中有一条由以下主键索引的记录:

s:22:"Informations générales";

问题是,现在(使用 UTF-8),当我序列化字符串时,我得到:

s:24:"Informations générales";

(注意字符串的大小现在是字节数,而不是字符串长度)

所以这与非utf8以前的记录不兼容!

我做错了吗?我该如何解决这个问题?

谢谢

【问题讨论】:

  • @Col Shrapnel:这就是所谓的“法国”,因此并不奇怪。
  • 他指的不是语言。他使用序列化的 PHP 字符串作为主键。这很奇怪。
  • @Boldewyn 他可能指的不是法语。
  • 大声笑,你很有趣。我更喜欢回答:我知道,真的,这很奇怪,但这是一个非常特殊的情况,请忽略它^^(实际上这不是主键,但我有一种情况)到...你知道...无论如何)
  • 讽刺,你去吧...但是,它可能是有效的。想想唯一的 URI,如果那是本地部分(url 解码),那么将它用作主键是一个完全正当的理由。

标签: php serialization utf-8


【解决方案1】:

行为完全正确。两个不同编码的字符串会产生不同的字节流,从而产生不同的序列化字符串。

【讨论】:

  • 好的,这很正常:序列化过程需要内存长度,而不是字符串长度
  • @Matthieu:我知道这听起来很奇怪,但在 PHP 中字符串实际上是字节数组。如果您echo strlen($utf8EncodedString),您将获得相同的输出。 字符长度,需要mb_strlen()
  • 另一个:file_get_contents() 会给你一个字符串(即使在获取二进制文件的内容时)。套接字函数也是如此。
  • 是的,我知道这一切,只是我想确定序列化是使用“字符串长度”还是“内存大小”。显然这是内存大小,所以我只需要使用 PHP UTF-8 重新生成包含序列化数据(以前以 ISO 编码)的所有数据库记录
【解决方案2】:

将数据库转储到 latin1 中。

在命令行中:

sed  -e 's/latin1/utf8/g' -i ./DBNAME.sql

导入转换为 UTF-8 新数据库的文件。

使用 php 脚本更新每个字段。 进行查询,遍历每个字段并使用以下命令更新序列化字符串:

$str = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $str);

在那之后,我能够使用 unserialize() 以及所有使用 UTF-8 的东西。

【讨论】:

  • 最大的问题是,如果你的字符串中有双引号,它们前面会加上一个反斜杠,因为 PHP 不恰当地试图帮助你(这是“e”标志的副作用)。使用“preg_replace_callback”似乎是解决这个问题的好方法。
  • 你是对的@MichaelChaney。我最近遇到了这个问题,并通过在 preg_replace 中使用此正则表达式模式 /!s:(\d+):"(.*?)";!/s 而不是 !s:(\d+):"(.*?)";!se 来修复它。不确定这个是否有任何副作用或缺点。
【解决方案3】:

要反序列化一个 utf-8 编码的序列化数组:

$array = @unserialize($arrayFromDatabase);
if ($array === false) {
  $array =  @unserialize(utf8_decode($arrayFromDatabase)); //decode first
  $array = array_map('utf8_encode', $array ); // encode the array again
}

【讨论】:

  • 当您有预先存在的以 ISO-8859-X 编码的序列化数据并且需要在移植到 UTF-8 的应用程序中使用它时,我发现此解决方案非常有用。
【解决方案4】:

PHP 4 和 5 没有内置的 Unicode 支持;我相信 PHP 6 开始添加更多的 Unicode 支持,尽管我不确定这有多完善。

【讨论】:

  • 我知道,我只是想知道“主键”的情况
【解决方案5】:

你没有做错什么。 v6 之前的 PHP 不支持 Unicode,因此不支持它,如果你没有击败它(即,通过 mbstring 扩展或其他方式)。

我们在这里围绕serialize() 编写了自己的包装器来解决这个问题。您也可以转向其他序列化技术,例如 JSON(自 5.2.0 起在 PHP 中使用 json_encode()json_decode())。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-06
    • 2014-03-18
    • 1970-01-01
    • 2018-03-01
    • 1970-01-01
    • 2021-06-25
    • 2012-08-15
    • 1970-01-01
    相关资源
    最近更新 更多