BeWithYou

胡搞的技术博客

  1. 首页
  2. PHP
  3. PHP过滤字符串中4字节utf8字符

PHP过滤字符串中4字节utf8字符


抓取第三方接口的时候发现有一些字段无法入库,本来以为是字段长度太大,于是加大了mysql的字段长度,发现还是不行。详细跟进到具体记录时,发现这样的记录存在特殊符号,这样的符号只有在firefox下才能看到占位。但是接口字符确实是utf8编码的,那为何会有非法字符呢?

utf8是变长编码,我们常用的汉字编码是3字节,但是还存在4字节编码的特殊符号,如emoji表情等等。mysql在比较新的版本里添加了utf8mb4编码的支持,但是我们线上数据库依然是5.1的老版本。只能在代码中将特殊字符过滤掉了。

直接从百度百科copy下来这段表格。

Unicode/UCS-4 bit数 UTF-8 byte数 备注
0000 ~007F 0~7 0XXX XXXX 1
0080 ~07FF 8~11 110X XXXX10XX XXXX 2
0800 ~FFFF 12~16 1110XXXX10XX XXXX10XX XXXX 3 基本定义范围:0~FFFF
1 0000 ~1F FFFF 17~21 1111 0XXX10XX XXXX10XX XXXX10XX XXXX 4 Unicode6.1定义范围:0~10 FFFF
20 0000 ~3FF FFFF 22~26 1111 10XX10XX XXXX10XX XXXX10XX XXXX10XX XXXX 5 说明:此非unicode编码范围,属于UCS-4 编码早期的规范UTF-8可以到达6字节序列,可以覆盖到31位元(通用字符集原来的极限)。尽管如此,2003年11月UTF-8 被 RFC 3629 重新规范,只能使用原来Unicode定义的区域, U+0000到U+10FFFF。根据规范,这些字节值将无法出现在合法 UTF-8序列中
400 0000 ~7FFF FFFF 27~31 1111 110X10XX XXXX10XX XXXX10XX XXXX10XX XXXX10XX XXXX 6

可以看到1-3字节的utf8编码字符,对应的unicode编码范围是0~FFFF,而1-4字节的utf8编码字符,对应的unicode编码范围是0~10 FFFF。那么显而易见,4字节编码的utf8字符,对应unicode范围是10000~10FFFF

所以我们在代码中使用preg_replace直接将4字节字符过滤掉即可。

//这里/u的修饰符表示使用unicode编码
$str = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $str);

之后就可以成功入库了。

回到顶部