php函数str_replace在GBK编码下替换特殊中文符号【】的问题

【说明】 本文转载自:http://www.miss77.net/433.html

近日,公司的论坛管理员发了一个帖子链接给我,说标题修改以后和实际的显示不一样。我打开之后发现,原始标题为:“手贱洗包浆,洗洗更健康”,但在title显示成了 “手贱洗包浆,洗洗更降”。

于是乎,在本地测试环境下进行了编辑测试未发现异常,服务器上对其它帖子也进行了编辑保存也为发现问题。

看来需要跟踪一下源代码了,发现上面的标题在执行了一下代码之后发生了变化:

1 $thread['subject'] = str_replace("【",'',$thread['subject']);
2 $thread['subject'] = str_replace("】",'',$thread['subject']);

至此,可以肯定问题出在了这里,然而到底是什么问题导致的呢,初步考虑是

1. 服务器环境有问题

2. 编码处理不一致

经过多个服务器环境测试后,发现问题依旧,可以排除服务器因素。

之后测试编码处理,先将要替换的字符和查询的字符串转成UTF-8编码,之后进行替换测试发现问题不存在了。

于是修正上面的代码为:

1 $rep1 = iconv('GBK', 'UTF-8', "【");
2 $rep2 = iconv('GBK', 'UTF-8', "】");
3 $thread['subject'] = iconv('GBK', 'UTF-8', $thread['subject']);
4 $thread['subject'] = str_replace(array($rep1, $rep2),array('',''), $thread['subject']);
5 $thread['subject'] = iconv('UTF-8', 'GBK', $thread['subject']);

解决问题。

终极问题分析:

由于计算机是基于二进制代码运行的,因此php在执行替换的时候也是将非ASCII字符转成了ASCII编码之后进行查找替换,使用十六进制工具查看这些字符的二进制情况,结果如下:

【 的十六进制为 A1 BE

】 的十六进制为 A1 BF

健康的十六进制为 BD A1 BF B5

降的十六进制为 BD B5

通过以上的十六进制数据不难发现,健康的ASCII码里面正好存在】的ASCII码,于是被替换,留下了降的ASCII码。

由此可知,在字符串查找替换的时候,如果是非ASCII编码字符串很容易出现这种问题,通过转码到UTF8或者Unicode编码能否彻底的解决此问题还有待考证!

2011/02/16 暖冬 PHP技术

此条目发表在未分类分类目录,贴了标签。将固定链接加入收藏夹。