PHP substr 截取 UTF8字符串乱码的解决
PHP的substr方法可以按照字节来截取字符串, 对于英文来说是没问题的. 因为一个英文字符只占一个字节.
但是对于截取UTF8编码的中文就会存在问题.
比如:
var $str = '我爱twitter哈哈 ';
echo substr($str, 0, 1);
就会出现一个乱字符, 因为在php中, utf8编码的中文是占3个字节, 单单只取一个字节肯定是不行啦.
如果: echo substr($str, 0, 3)
就会出现"我"
echo substr($str, 0, 9)
会出现"我爱twi"
在中英文混排的时候, 这个函数就显得无能为力了.
google了一下, 发现很多人写了替代方法, 比如自己去实现一个substr, 里面写循环.
这样肯定效率低下, 直接用substr的复杂度是1, 而自己写循环, 复杂度就是n了.
后来找到了Wikipedia的条目, 发现原来3字节的utf8编码是有规律的.
一个非英文字符的3-bytes utf8 编码, 总是以224-239之间的char code开头的, 这就好办了.
思路是这样的:
先用substr截取, 判断截取结果的最后一位是不是在224-239之间, 如果是, 就说明目前取到了3-byte utf8编码的第一位, 那么只需要把计划截取的长度-1即可.
如果截取结果的最后一位之前一位在224-239之间, 就说明目前取到了3-byte utf8编码的第二位, 只需要将计划截取的长度-2即可.
下面是代码:
function csubstr($string, $beginIndex, $length){
if(strlen($string) < $length){
return substr($string, $beginIndex);
}
$char = ord($string[$beginIndex + $length - 1]);
if($char >= 224 && $char <= 239){
$str = substr($string, $beginIndex, $length - 1);
return $str;
}
$char = ord($string[$beginIndex + $length - 2]);
if($char >= 224 && $char <= 239){
$str = substr($string, $beginIndex, $length - 2);
return $str;
}
return substr($string, $beginIndex, $length);
}