2013-05-11 198 views
16

我在一个mysql 5.1服务器中使用utf8 charset mysql表,它不支持表中的utf8mb4编码。插入4字节编码的utf8字符时,如"","","","","","唧",""。该表将弹出错误或跳过以下文本。php可以检测4字节编码的utf8字符吗?

如何以编程方式检测PHP中的4字节编码utf8字符并将其替换?

+0

很简单:通过分割字符的字符串(很多方法可以做到这一点),并检查是否'的strlen($字符)== 4'。不确定这是否是真正的检测MySQL无法处理的字符的正确方法,通过代码点进行更准确。 – deceze 2013-05-11 11:26:03

+0

你检出了[多字节扩展](http://php.net/mbstring)吗?另外,一定要[阅读评论](http://dk1.php.net/manual/en/function.mb-internal-encoding.php#66568)。 – 2013-05-11 11:30:29

+0

@deceze这是一种方法。如果没有其他优雅的方式,我会这样做。 – 2013-05-11 11:36:37

回答

13

下面的正则表达式将取代4个字节的UTF-8字符:

function replace4byte($string, $replacement = '') { 
    return preg_replace('%(?: 
      \xF0[\x90-\xBF][\x80-\xBF]{2}  # planes 1-3 
     | [\xF1-\xF3][\x80-\xBF]{3}   # planes 4-15 
     | \xF4[\x80-\x8F][\x80-\xBF]{2}  # plane 16 
    )%xs', $replacement, $string);  
} 

var_dump(replace4byte('d'), replace4byte('dd')); 

这并不依靠/u修改,所以你不应该需要担心UTF-8作为PCRE编译。但是,如果你有这种支持,deceze的preg_replace_callback是整洁。

(正则表达式从Ensuring valid utf-8 in PHP改编)

13

这应该工作:

if (max(array_map('ord', str_split($string))) >= 240) 

理性在于代码点直到并包括U + FFFF被编码为三个字节形式1110xxxx 10xxxxxx 10xxxxxx的。较高的代码点的格式为11110xxx 10xxxxxx 10xxxxxx 10xxxxxx,即最高字节的值为240或更高。如果字符串中有任何这样的字节,则它是4字节序列的指示符。

如果你想删除字符,这会做:

preg_replace_callback('/./u', function (array $match) { 
    return strlen($match[0]) >= 4 ? null : $match[0]; 
}, $string) 

虽然有可能直接表达高码点更优雅的正则表达式的方法。

+0

感谢您的检测,但您是否可以使用替换示例来完成它? $ a =“omg,我无法插入我的表,blahblahblah”; // target $ a ==“omg,我无法将MYTEXT插入到我的表中,blahblahblah”; – 2013-05-11 11:48:22