关闭

PHP截取UTF8字符串 utf-8 可以能占一个字符 二个字符 或者三个字符

3799人阅读 评论(0) 收藏 举报
分类:

PHP截取UTF8字符串  


想必很多人从一开始接触编程到现在,都有一个惯性思维:英文字符占用一个字节,中文字符占用两个字节。不错,英文字符是占用一个字节,但中文字符占用两个字节是相对于GBK编码而言(当然,其他一些编码如GB2312也是),但是在时下国际流行的UTF8编码中,一个中文字符占用3个字节。不要惊讶,这是一个事实,而且应该成为一个常识。
UTF8编码可能出现一个字符占用1个、2个、3个甚至更多字节的情况,如英文字符abc占用一个字节,中文字符占用三个字节,那么什么字符占用两个字节呢?这个问题我一开始并没有发现,只是前几天有人留言,首页的评论截取竟然出现了乱码的情况:

2011年09月21日 - bzyyc.happy - 点烟看寂寞燃烧
最开始并没有发现这两个乱码出现的问题在哪里,后来仔细验证了下,发现是处在·这个字符上(键盘左上角,中文输入法下),它占用两个字节。而emlog的截取字符串函数,除了英文字符外,默认其他的都占三个字节了,因此导致乱码出现。
查阅了相关资料,得出了一个结论:UTF8编码的字符中,第一个字节ASCII值大于等于224的,其与之后的2个字节一起组成一个UTF8字符,第一个字节ASCII值大于192等于小于224的,其与之后的1个字节组成一个UTF-8字符,第一个字节ASCII值小于192的,其本身成为一个UTF8字符。于是在PHP中将·字符的ASCII打印出来,第一个字节是194,第二个字节是183,木有第三个字节了,于是截取的字符中,若包含·字符,就会出现乱码了。
问题找到,解决方案也就很简单了,分别判断处理下就OK。写了如下函数用于截取:


function subString($str, $start, $length) {
    $i = 0;
    //完整排除之前的UTF8字符
    while($i < $start) {
        $ord = ord($str{$i});
        if($ord < 192) {
            $i++;
        } elseif($ord <224) {
            $i += 2;
        } else {
            $i += 3;
        }
    }
    //开始截取
    $result = '';
    while($i < $start + $length && $i < strlen($str)) {
        $ord = ord($str{$i});
        if($ord < 192) {
            $result .= $str{$i};
            $i++;
        } elseif($ord <224) {
            $result .= $str{$i}.$str{$i+1};
            $i += 2;
        } else {
            $result .= $str{$i}.$str{$i+1}.$str{$i+2};
            $i += 3;
        }
    }
    if($i < strlen($str)) {
        $result .= '...';
    }
    return $result;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:301206次
    • 积分:3521
    • 等级:
    • 排名:第9725名
    • 原创:61篇
    • 转载:73篇
    • 译文:0篇
    • 评论:16条
    文章分类
    最新评论