UTF8特殊空格导致编码转换失败的问题

有个项目中,我用到了其他部门提供的新闻接口,需要将其返回结果中的摘要字段存入数据库,然后再通过定时脚本发送给另外一个功能,大致流程如下:

我从W部门的接口获取UTF8数据->存入本地数据库->定时脚本查询本地数据库->生成GBK文件->同步给其他功能使用

有一天产品经理反馈,一个新闻的摘要信息是空的。我看了下,我这边数据库里是有数据的,但是生成的GBK文件里面,确实没数据,然后仔细看了下数据库中存储的摘要信息,发现有不能识别的内容:

特殊的UTF8空格字符

我将这段文本每个字的ASCII码打印出来,发现这些不能识别的内容,其实也是汉字,这部分字符应该是UTF8专有的,GBK里面没有,因此我通过iconv将整段文本从UTF8转为GBK时,得到的是false;通过mb_convert_encoding转换后,得到的是问号(????)。

后来在网上搜了下,发现有人遇到和我一样的问题,参考这个文章

在于UTF-8这种编码里面,存在一个特殊的字符,其编码是“0xC2 0xA0”(194 160),转换成字符的时候,表现为一个空格,跟一般的半角空格(ASCII 0x20)一样,唯一的不同是它的宽度不会被压缩,因此比较多的被用于网页排版(如首行缩进之类)。而其他的编码方式如GB2312、Unicode之类并没有这样的字符。

后来我把这个特殊空格转为普通的空格,解决了这个问题。

总结:

1.遇到字符转换的问题,如果字符不能肉眼识别,可以通过打印其ASCII码来帮助排查问题。

2.PHP中的字符转换函数:

获取文本的ASCII码:ord(String s),通过ord()函数获取字符的ASCII码值,如果返回值大于 127则表示为中文字符的一半,再获取后一半组合成一个完整字符

返回ASCII对应的字符:chr(int),参数可以是任意进制的数值,不局限于10机制