mb_strwidth($str, $encoding) 返回字串的寬度
$str 要計算的字串
$encoding 要使用的編碼,如 utf8、gbk
mb_strimwidth($str, $start, $width, $tail, $encoding) 按寬度截取字串
$str 要截取的字串
$start 從哪個位置開始截取,預設是0
$width 要截取的寬度
$tail 追加到截取字串後邊的字串,常用的是 ...
$encoding 要使用的編碼
| 代碼如下 |
複製代碼 |
<?php /** * utf8 編碼格式 * 1個中文佔用3個位元組 * 我們希望的是1個中文佔用2個位元組, * 因為從寬度上看2個英文字母佔用的位置相當於1個中文 */
// 測試字串 $str = 'aaaa啊啊aaaa啊啊啊aaa'; echo strlen($str); // 只用strlen輸出為25個位元組 // 必須指定編碼,不然會使用php的內碼 mb_internal_encoding()可以查看內碼 // 使用mb_strwidth輸出字串的寬度為20使用utf8編碼 echo mb_strwidth($str, 'utf8'); // 只有寬度大於10才截取 if(mb_strwidth($str, 'utf8')>10){ // 此處設定從0開始截取,取10個追加...,使用utf8編碼 // 注意追加的...也會被計算到長度之內 $str = mb_strimwidth($str, 0, 10, '...', 'utf8'); } // 最後輸出 aaaa啊... 4個a算4個 1個啊算2個 3個點算3個 4+2+3=9 // 是不是很簡單啊,有的人說了為什麼是9個不是10個嗎? // 因為正好“啊”的後邊還是“啊”,中文算2個,9+2=11 超出了設定,所以去掉1個就是9了 echo $str; |
如果對於全中文沒有問題但如果中間有符號了就有問題了,如我使用mb_strimwidth,mb_strwidth,後發現如果標題中存在“”符號的時候,PHP mb_strwidth會將該符號認為是1個寬度,我納悶了這個不是中文的雙引號嘛,照理說肯定是寬位元組的,長度應該是2個寬度,後查詢“”unicode分別為u201C和u201D,不在中文字元的範圍中,再查詢unicode.org 的碼錶,發現u2000-u206F是通用符號的範圍,此範圍中的字元雖然都是寬字元的形式,但是PHP 的mb_函數卻認為是1個寬度,沒辦法,只能靠自己了。
| 代碼如下 |
複製代碼 |
function truncString($str, $length) { $countLen=0; for($i=0;$i<mb_strlen($str);$i++) { $countLen+=amb_strwidth(mb_substr($str,$i,1)); if($countLen>$length) return mb_substr($str,0,$i); } return $str; } function amb_strwidth($str_width) { $count=0; for($i=0;$i<mb_strlen($str_width);$i++) { //if(mb_substr($str_width,$i,1)=="\xE2\x80\x9C"||mb_substr($str_width,$i,1)=='\xE2\x80\x9D') //如果遇到u2000-u206F內的字元則將計數器加2 if(preg_match("/[\x{2000}-\x{206F}]/u",mb_substr($str_width,$i,1))) $count+=2; else $count+=mb_strwidth(mb_substr($str_width,$i,1)); } return $count; } |
總結,做來做出怎麼就感覺到這個變成了回原點了呢,感覺還是要使用到迴圈遍曆算字元編碼取字元位元哈。