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即可.

下面是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
}
Share
This entry was posted in 编程 and tagged , . Bookmark the permalink.

4 Responses to PHP substr 截取 UTF8字符串乱码的解决

  1. Pingback: 一生久久 » PHP截取中文汉字UTF-8字符串乱码的解决方法

  2. rk says:

    很好 已转载

  3. Fwolf says:

    试试mb_substr()

  4. LuciferSheng says:

    这个函数还有个问题,第一个字符还需要判断

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">