網路城邦

上一篇 回創作列表 下一篇   字體:
PHP substr切割中文字問題之處理
2009/12/08 10:02:11瀏覽2317|回應1|推薦1

PHP中的substr是以位元組來切割字串,如:

$content = "這是 bruse 的測試";
echo substr($content,0,15)."<br>";

在UTF-8的編碼下,因為中文字為3位元組,第15位元組是中文字三位元組中央,所以會印出:

這是 bruse 皼br>

其中可以看到"的"的前二位元組會把<br>的"<"拿去組字,造成中文字和程式碼的錯誤。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

有一種方法可以解決這個問題,就是使用mb_substr,並帶編碼,如:

$content = "這是 bruse 的測試";
echo mb_substr($content,0,15,"UTF-8");

使用mb_substr可以設定編碼,中文字會被判斷是1個字,因為content只有13字,所以15個中英文會全部印出:

這是 bruse 的測試


這樣是解決了切中文字的問題沒錯,但有時我們要把資料存進資料庫或是呈現出來,這時15個中文字並非是15個位元組,會造成程式的錯誤。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

所以,我們必須改寫substr,使用位元組的方式計算長度,但又不能出現中文字切割的錯誤,我們改寫substr為utf8_substr,程式如下:

function utf8_substr($StrInput,$strStart,$strLen)
{
//對字串做URL Eecode
$StrInput = mb_substr($StrInput,$strStart,mb_strlen($StrInput));
$iString = urlencode($StrInput);
$lstrResult="";
$istrLen = 0;
$k = 0;
do{
$lstrChar = substr($iString, $k, 1);
if($lstrChar == "%"){
$ThisChr = hexdec(substr($iString, $k+1, 2));
if($ThisChr >= 128){
if($istrLen+3 < $strLen){
$lstrResult .= urldecode(substr($iString, $k, 9));
$k = $k + 9;
$istrLen+=3;
}else{
$k = $k + 9;
$istrLen+=3;
}
}else{
$lstrResult .= urldecode(substr($iString, $k, 3));
$k = $k + 3;
$istrLen+=2;
}
}else{
$lstrResult .= urldecode(substr($iString, $k, 1));
$k = $k + 1;
$istrLen++;
}
}while ($k < strlen($iString) && $istrLen < $strLen);
return $lstrResult;
}

$content = "這是 bruse 的測試";
echo utf8_substr($content,0,15);

上面的程式碼如果遇到切在中文字中,就會跳出,所以會印出:

這是 bruse

這樣就解決了以上的問題,不過呈現時若使用strlen判斷長度再切,因為中文在UTF-8中是三個位元組,而英文是一個位元組,但中文和英文的字寬度並不到三倍,大約只有一倍,所以會變成長度差太多,此時,我們就得連strlen也改寫。

( 興趣嗜好電腦3C )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=maxmas&aid=3568169

 回應文章

麥克斯
等級:6
留言加入好友
mb_strcut函數功能也可以截取字符串長度
2009/12/08 10:21

mb_strcut函數功能也可以截取字符串長度,下面看看具體實例區別在哪:

$str ='這樣一來我的字符串就不會有亂碼^_^';
echo"mb_substr:".mb_substr($str,0,7,'utf-8');
輸出結果:這樣一來我的字

echo"mb_strcut:".mb_strcut($str,0,6,'utf-8');
輸出結果:這樣

從上面的例子可以看出,mb_substr是按字來切分,而mb_strcut是按字元來切分字符,但是都不會產生半個字符的現象。

註:一個UTF-8的中文佔3 bytes.


╭★╯﹒*★﹒╰★╮﹒╭★╯﹒★*﹒╰★╮
   麥克斯工作室-客製化網站製作
      www.maxmas.biz
╭★╯﹒*★﹒╰★╮﹒╭★╯﹒★*﹒╰★╮