完全轉換UTF-8爲GB2312的PHP函數

  開始是用“$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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章