2015-04-01 19 views
0

我使用PHP函数serialize来序列化一个大字符串的对象,在字符串中有一个特殊字符“ - ”。当数据库使用latin1字符集时,该对象被保存,现在我将数据库迁移到UTF-8。PHP函数反序列化在charset更改后停止工作(从latin1到UTF-8)

我使用PHP函数unserialize来取回对象,因为我将字符集更改为UTF-8,该函数停止工作。我不知道为什么。

我修改httpd.conf中使用:

AddCharset UTF-8 .utf8 
AddDefaultCharset UTF-8 

的php.ini:

default_charset = "UTF-8" 

而且所有MySQL的数据转换为UTF-8。

UPDATE 我赶上了PHP的错误,当我调用反序列化功能:

unserialize(): Error at offset 19146 of 23672 bytes in /xxx/xxx.php:18 
+0

执行'SELECT col,HEX(col)...'向我们展示淘气角色的十六进制。这将有助于确定数据库中的数据是错误的还是从数据库获取数据后正在处理不正确的数据。 – 2015-04-01 18:56:20

+0

HEX是E28094,谢谢瑞克。 – Tony 2015-04-02 15:29:53

+0

看起来它是一个UTF-8字符(http://www.fileformat.info/info/unicode/char/2014/index.htm),所以mysql方面是正确的,并且问题出现在apache/php中? – Tony 2015-04-02 15:31:40

回答

0

我发现从latin1改为UTF-8后,序列化字符串的长度是错误的。 我修复使用此PHP问题:

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

我将更新为新的字符串数据基础。

+0

也许最好是使用json_encode/decode而不是un/serialize? – 2015-04-03 17:35:45

1

现在,请不要SHOW CREATE TABLE ...并显示结果。

如果将E28094存储的列的CHARACTER SET设置为latin1,则表示混乱。它需要转换为十六进制97,EM-dash的latin1编码,但不是。可能你有utf8字节,但是(默认情况下)告诉MySQL你有utf8字节。它可能会读为“ - ” - 每个字节的latin1解码。这是因为MySQL认为它是3个拉丁字符。 Here is the likely solution.但是,要谨慎。

如果列的CHARACTER SET是utf8,那么表中的所有内容都很好。

像这样的问题的冗长讨论是在my blog

+0

-The列LONGTEXT COLLATE utf8_unicode_ci NOT NULL -The表是ENGINE = InnoDB的默认字符集= UTF8 COLLATE = utf8_unicode_ci” 之前LATIN1 – Tony 2015-04-02 16:46:01

+0

我用这个查询latin1和UTF-8迁移: ALTER DATABASE 字符集UTF8 COLLATE utf8_unicode_ci; ALTER TABLE

转换为字符集utf8 COLLATE utf8_unicode_ci; – Tony2015-04-02 16:52:14

+0

EM-dash是否正确打印?HEX是否仍然说E28094? – 2015-04-02 21:17:23