PHP內建的substr()函數不能對中文字元進行很好的截斷處理,對於一些中英文混合的字元會出現亂碼的情況。下面提供兩種解決函數。
1、GB2312編碼方式的截斷、
1 function msubstr($str, $start, $len) { 2 3 if (strlen($str)-$start < $len) return false; 4 5 $tmpstr = ""; 6 7 $strlen = $start + $len; 8 9 for($i = 0; $i < $strlen; $i++) {10 11 if(ord(substr($str, $i, 1)) > 0xa0) { //0xa0 表示中文漢字編碼的第一個編碼字元ASCII 碼值都大於0xa012 13 $tmpstr .= substr($str, $i, 2);14 15 $i++;16 17 } else18 19 $tmpstr .= substr($str, $i, 1);20 21 }22 23 return $tmpstr . "...";24 25 }
2、utf8格式下的中文字元截斷
UTF-8編碼的字元可能由1~3個位元組組成, 具體數目可以由第一個位元組判斷出來。(理論上可能更長,但這裡假設不超過3個位元組)
第一個位元組大於224的,它與它之後的2個位元組一起組成一個UTF-8字元
第一個位元組大於192小於224的,它與它之後的1個位元組組成一個UTF-8字元
否則第一個位元組本身就是一個英文字元(包括數字和一小部分標點符號)。
1 //$sourcestr 是要處理的字串 2 3 //$cutlength 為截取的長度(即字數) 4 5 function cut_str($sourcestr,$cutlength) 6 7 { 8 9 $returnstr='';10 11 $i=0;12 13 $n=0;14 15 $str_length=strlen($sourcestr);//字串的位元組數16 17 while (($n<$cutlength) and ($i<=$str_length))18 19 {20 21 $temp_str=substr($sourcestr,$i,1);22 23 $ascnum=Ord($temp_str);//得到字串中第$i位字元的ascii碼24 25 if ($ascnum>=224) //如果ASCII位高與224,26 27 {28 29 $returnstr=$returnstr.substr($sourcestr,$i,3); //根據UTF-8編碼規範,將3個連續的字元計為單個字元 30 31 $i=$i+3; //實際Byte計為332 33 $n++; //字串長度計134 35 }36 37 elseif ($ascnum>=192) //如果ASCII位高與192,38 39 {40 41 $returnstr=$returnstr.substr($sourcestr,$i,2); //根據UTF-8編碼規範,將2個連續的字元計為單個字元42 43 $i=$i+2; //實際Byte計為244 45 $n++; //字串長度計146 47 }48 49 elseif ($ascnum>=65 && $ascnum<=90) //如果是大寫字母,50 51 {52 53 $returnstr=$returnstr.substr($sourcestr,$i,1);54 55 $i=$i+1; //實際的Byte數仍計1個56 57 $n++; //但考慮整體美觀,大寫字母計成一個高位字元58 59 }60 61 else //其他情況下,包括小寫字母和半形標點符號,62 63 {64 65 $returnstr=$returnstr.substr($sourcestr,$i,1);66 67 $i=$i+1; //實際的Byte數計1個68 69 $n=$n+0.5; //小寫字母和半形標點等與半個高位字元寬...70 71 }72 73 }74 75 if ($str_length>$cutlength){76 77 $returnstr = $returnstr . "...";//超過長度時在尾處加上省略符號78 79 }80 81 return $returnstr;82 83 }
參考:http://bupt-roy.iteye.com/blog/1179016
http://zww.me/archives/25356
http://imluren.com/2011/04/php-utf8-substr.html/comment-page-1