開始是用“$re=iconv("UTF-8","GB2312",$snoopy->results);”將utf8轉換成gb2312,結果經常出錯,到了一半就看不到後文了。後來用“$re=iconv("UTF-8","GB2312//IGNORE",$snoopy->results);”,加上了忽略錯誤,好了點,可以轉換到底了!可是今天又發現,還是有部分網頁無法轉換。後來仔細研究發現原來iconv只能轉換3字符的utf8碼,如果需要全碼轉換需要另外寫函數。
首先需要了解utf8的構成。
基礎:
1、單獨使用iconv函數只能轉換GB2312字符,外文字符無法轉換。
2、沒有現成的函數可以用。
3、bindec()函數:將二進制格式的“01”字符串轉換爲十進制數。
4、decbin()函數:將十進制數轉換爲二進制字符串,如decbin(224)="11100000"。
思路:因爲UTF-8分別有1、2、3字節編碼,中日韓文都是3字節編碼,處理時根據字符編碼中首字節大小區分字節數量。
1、如首字節小於128,爲ASCII碼。
2、128~192,非UTF-8編碼,且處理爲“&#ord();”。
3、192~224, 雙字節UTF-8編碼。
4、224~240,三字節編碼。
5、240~248,四字節編碼。
6、……
7、對於三字節編碼的嘗試用iconv轉換成GB2312。
8、非GB2312的多字節字符,嘗試把UTF-8轉換成Unicode,再取到Unicode十進制值。
9、可以考慮使用位運算,也可以用bindec()函數。
程序代碼:
function GetGB2312String($name) { $tostr = ""; for($i=0;$i<strlen($name);$i++) { $curbin = ord(substr($name,$i,1)); if($curbin < 0x80) { $tostr .= substr($name,$i,1); }elseif($curbin < bindec("11000000")){ $str = substr($name,$i,1); $tostr .= "&#".ord($str).";"; }elseif($curbin < bindec("11100000")){ $str = substr($name,$i,2); $tostr .= "&#".GetUnicodeChar($str).";"; $i += 1; }elseif($curbin < bindec("11110000")){ $str = substr($name,$i,3); $gstr= iconv("UTF-8","GB2312",$str); if(!$gstr) { $tostr .= "&#".GetUnicodeChar($str).";"; }else{ $tostr .= $gstr; } $i += 2; }elseif($curbin < bindec("11111000")){ $str = substr($name,$i,4); $tostr .= "&#".GetUnicodeChar($str).";"; $i += 3; }elseif($curbin < bindec("11111100")){ $str = substr($name,$i,5); $tostr .= "&#".GetUnicodeChar($str).";"; $i += 4; }else{ $str = substr($name,$i,6); $tostr .= "&#".GetUnicodeChar($str).";"; $i += 5; } } return $tostr; }//end function function GetUnicodeChar($str) { $temp = ""; for($i=0;$i<strlen($str);$i++) { $x = decbin(ord(substr($str,$i,1))); if($i == 0) { $s = strlen($str)+1; $temp .= substr($x,$s,8-$s); }else{ $temp .= substr($x,2,6); } } return bindec($temp); }//end function |
程序使用:
$re=GetGB2312String($snoopy->results); |
開始是用“$re=iconv("UTF-8","GB2312",$snoopy->results);”將utf8轉換成gb2312,結果經常出錯,到了一半就看不到後文了。後來用“$re=iconv("UTF-8","GB2312//IGNORE",$snoopy->results);”,加上了忽略錯誤,好了點,可以轉換到底了!可是今天又發現,還是有部分網頁無法轉換。後來仔細研究發現原來iconv只能轉換3字符的utf8碼,如果需要全碼轉換需要另外寫函數。
首先需要了解utf8的構成。
基礎:
1、單獨使用iconv函數只能轉換GB2312字符,外文字符無法轉換。
2、沒有現成的函數可以用。
3、bindec()函數:將二進制格式的“01”字符串轉換爲十進制數。
4、decbin()函數:將十進制數轉換爲二進制字符串,如decbin(224)="11100000"。
思路:因爲UTF-8分別有1、2、3字節編碼,中日韓文都是3字節編碼,處理時根據字符編碼中首字節大小區分字節數量。
1、如首字節小於128,爲ASCII碼。
2、128~192,非UTF-8編碼,且處理爲“&#ord();”。
3、192~224, 雙字節UTF-8編碼。
4、224~240,三字節編碼。
5、240~248,四字節編碼。
6、……
7、對於三字節編碼的嘗試用iconv轉換成GB2312。
8、非GB2312的多字節字符,嘗試把UTF-8轉換成Unicode,再取到Unicode十進制值。
9、可以考慮使用位運算,也可以用bindec()函數。
程序代碼:
function GetGB2312String($name) { $tostr = ""; for($i=0;$i<strlen($name);$i++) { $curbin = ord(substr($name,$i,1)); if($curbin < 0x80) { $tostr .= substr($name,$i,1); }elseif($curbin < bindec("11000000")){ $str = substr($name,$i,1); $tostr .= "&#".ord($str).";"; }elseif($curbin < bindec("11100000")){ $str = substr($name,$i,2); $tostr .= "&#".GetUnicodeChar($str).";"; $i += 1; }elseif($curbin < bindec("11110000")){ $str = substr($name,$i,3); $gstr= iconv("UTF-8","GB2312",$str); if(!$gstr) { $tostr .= "&#".GetUnicodeChar($str).";"; }else{ $tostr .= $gstr; } $i += 2; }elseif($curbin < bindec("11111000")){ $str = substr($name,$i,4); $tostr .= "&#".GetUnicodeChar($str).";"; $i += 3; }elseif($curbin < bindec("11111100")){ $str = substr($name,$i,5); $tostr .= "&#".GetUnicodeChar($str).";"; $i += 4; }else{ $str = substr($name,$i,6); $tostr .= "&#".GetUnicodeChar($str).";"; $i += 5; } } return $tostr; }//end function function GetUnicodeChar($str) { $temp = ""; for($i=0;$i<strlen($str);$i++) { $x = decbin(ord(substr($str,$i,1))); if($i == 0) { $s = strlen($str)+1; $temp .= substr($x,$s,8-$s); }else{ $temp .= substr($x,2,6); } } return bindec($temp); }//end function |
程序使用:
$re=GetGB2312String($snoopy->results); |