关于PHP utf-8文本截取乱码的原因与解决办法

一直以来的惯性思维,都认为英文和数字字符占用一个字节,汉字占用2个字节,实际上GBK(GB2312)确实是这样的,但是当我使用UTF-8编码的时候发现,utf-8汉字所占用的字节数是不一样的,utf-8编码可能会出现一个汉字占用1个-、2个、3个甚至可能更多的可能。 这样,我们在截取时,还按照2个字节一个汉字去截取必然会出现乱码。

查阅了一些资料,发现UTF8编码的字符,第一个字节ASCII值大于等于224的,其与之后的2个字节一起组成一个UTF8字符,第一个字节ASCII值大于192等于小于224的,其与之后的1个字节组成一个UTF-8字符,第一个字节ASCII值小于192的,其本身成为一个UTF8字符。

于是在PHP中,只用一个字,把字符的ASCII打印出来,第一个字节是225,第二个字节是193,第三个字节 184,于是截取的字符只截取了前2个,没有第三个字节,就会出现乱码了。
于是解决办法就很好处理了,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function subString($str,$start,$length){
    #61原创函数
    #$str被截取的文字
    #$start 开始位置
    #$length 截取长度、汉字个数,数字与英文也算一个字
    $spLen = strlen($str);  //取文本长度
    $start--;
    //遍历所有文字
    for($i=0;$i<$spLen;)
    {
	if (ord($str[$i])>=224){
	    $c = $str[$i].$str[$i+1].$str[$i+2];
	    $j=3;
	}elseif (ord($str[$i])>=192 && ord($str[$i])<224){
	    $c = $str[$i].$str[$i+1];
	    $j=2;
	}elseif (ord($str[$i])<192){
	    $c = $str[$i];
	    $j=1;
	}
	//输出
	if ($i>=$start && $i<=$length){
	    $str_ok.=$c;
	}
	$i=$i+$j;
    }
    return $str_ok;
}

发表评论