欢迎您访问我爱IT技术网,今天小编为你分享的编程技术是:【php对gb编码动态转utf-8编码的几种方法评测】,下面是详细的分享!
php对gb编码动态转utf-8编码的几种方法评测
<?php
require_once ("func_ip.php");
function u2utf8($c) {
$str="";
if ($c < 0x80) {
$str .=$c;
} elseif ($c < 0x800) {
$str .=chr(0xC0 | $c >> 6);
$str .=chr(0x80 | $c & 0x3F);
} elseif ($c < 0x10000) {
$str .=chr(0xE0 | $c >> 12);
$str .=chr(0x80 | $c >> 6 & 0x3F);
$str .=chr(0x80 | $c & 0x3F);
} elseif ($c < 0x200000) {
$str .=chr(0xF0 | $c >> 18);
$str .=chr(0x80 | $c >> 12 & 0x3F);
$str .=chr(0x80 | $c >> 6 & 0x3F);
$str .=chr(0x80 | $c & 0x3F);
}
return $str;
}
function GB2UTF8_SQL($strGB) {
if (!trim($strGB)) return $strGB;
$strRet="";
$intLen=strlen($strGB);
for ($i=0; $i < $intLen; $i++) {
if (ord($strGB{$i}) > 127) {
$strCurr=substr($strGB, $i, 2);
$intGB=hexdec(bin2hex($strCurr)) - 0x8080;
$strSql="SELECT code_unicode FROM nnstats_gb_unicode
WHERE code_gb=".$intGB." LIMIT 1"
;
$resResult=mysql_query($strSql);
if ($arrCode=mysql_fetch_array($resResult)) $strRet .=u2utf8($arrCode["code_unicode"]);
else $strRet .="";
$i++;
} else {
$strRet .=$strGB{$i};
}
}
return $strRet;
}
function GB2UTF8_FILE($strGB) {
if (!trim($strGB)) return $strGB;
$arrLines=file("gb_unicode.txt");
foreach ($arrLines as $strLine) {
$arrCodeTable[hexdec(substr($strLine, 0, 6))]=hexdec(substr($strLine, 7, 6));
}
$strRet="";
$intLen=strlen($strGB);
for ($i=0; $i < $intLen; $i++) {
if (ord($strGB{$i}) > 127) {
$strCurr=substr($strGB, $i, 2);
$intGB=hexdec(bin2hex($strCurr)) - 0x8080;
if ($arrCodeTable[$intGB]) $strRet .=u2utf8($arrCodeTable[$intGB]);
else $strRet .="";
$i++;
} else {
$strRet .=$strGB{$i};
}
}
return $strRet;
}
function EncodeIp($strDotquadIp) {
$arrIpSep=explode('.', $strDotquadIp);
if (count($arrIpSep) !=4) return 0;
$intIp=0;
foreach ($arrIpSep as $k=> $v) $intIp +=(int)$v * pow(256, 3 - $k);
return $intIp;
//return sprintf('%02x%02x%02x%02x', $arrIpSep[0], $arrIpSep[1], $arrIpSep[2], $arrIpSep[3]);
}
function GetMicroTime() {
list($msec, $sec)=explode(" ", microtime());
return ((double)$msec + (double)$sec);
}
for ($i=0; $i < 100; $i++) { // 随机产生100个ip地址
$strIp=mt_rand(0, 255).".".mt_rand(0, 255).".".mt_rand(0, 255).".".mt_rand(0, 255);
$arrAddr[$i]=ip2addr(EncodeIp($strIp));
}
$resConn=mysql_connect("localhost", "netnest", "netnest");
mysql_select_db("test");
// 测评MySQL查询的编码转换
$dblTimeStart=GetMicroTime();
for ($i=0; $i < 100; $i++) {
$strUTF8Region=GB2UTF8_SQL($arrAddr[$i]["region"]);
$strUTF8Address=GB2UTF8_SQL($arrAddr[$i]["address"]);
}
$dblTimeDuration=GetMicroTime() - $dblTimeStart;
// 测评结束并输出结果
echo $dblTimeDuration; echo "\r\n";
// 测评文本文件查询的编码转换
$dblTimeStart=GetMicroTime();
for ($i=0; $i < 100; $i++) {
$strUTF8Region=GB2UTF8_FILE($arrAddr[$i]["region"]);
$strUTF8Address=GB2UTF8_FILE($arrAddr[$i]["address"]);
}
$dblTimeDuration=GetMicroTime() - $dblTimeStart;
// 测评结束并输出结果
echo $dblTimeDuration; echo "\r\n";
?>
可见这次是MySQL方法遥遥领先于文件查询法。但是现在还不急于使用MySQL方法,因为文本文件方法之所以如此耗时,主要因为它每次转换都要把整个gb_unicode.txt读入内存,而gb_unicode.txt又是文本文件,格式如下:
0x2121 0x3000 # IDEOGRAPHIC SPACE 0x2122 0x3001 # IDEOGRAPHIC COMMA 0x2123 0x3002 # IDEOGRAPHIC FULL STOP 0x2124 0x30FB # KATAKANA MIDDLE DOT 0x2125 0x02C9 # MODIFIER LETTER MACRON (Mandarin Chinese first tone) …… 0x552A 0x6458 # <CJK> 0x552B 0x658B # <CJK> 0x552C 0x5B85 # <CJK> 0x552D 0x7A84 # <CJK> …… 0x777B 0x9F37 # <CJK> 0x777C 0x9F3D # <CJK> 0x777D 0x9F3E # <CJK> 0x777E 0x9F44 # <CJK> |
文本文件效率较低,于是考虑把文本文件转换为二进制文件,然后用折半法查找这个文件,而不需要把整个文件读入内存。文件格式为:文件头2字节,存储记录数;接着一条接一条记录存入文件,每条记录4字节,前2字节对应GB代码,后2字节对应Unicode代码。转换程序如下:
<?php $arrLines=file("gb_unicode.txt"); foreach ($arrLines as $strLine) { $arrCodeTable[hexdec(substr($strLine, 0, 6))]=hexdec(substr($strLine, 7, 6)); } ksort($arrCodeTable); $intCount=count($arrCodeTable); $strCount=chr($intCount % 256) . chr(floor($intCount / 256)); $fileGBU=fopen("gbu.dat", "wb"); fwrite($fileGBU, $strCount); foreach ($arrCodeTable as $k=> $v) { $strData=chr($k % 256) . chr(floor($k / 256)) . chr($v % 256) . chr(floor($v / 256)); fwrite($fileGBU, $strData); } fclose($fileGBU); ?> |
执行程序后就获得了二进制的GB->Unicode对照表gbu.dat,并且数据记录按GB代码排了序,便于折半法查找。使用gbu.dat进行转码的函数如下:
function GB2UTF8_FILE1($strGB) { if (!trim($strGB)) return $strGB; $fileGBU=fopen("gbu.dat", "rb"); $strBuf=fread($fileGBU, 2); $intCount=ord($strBuf{0}) + 256 * ord($strBuf{1}); $strRet=""; $intLen=strlen($strGB); for ($i=0; $i < $intLen; $i++) { if (ord($strGB{$i}) > 127) { $strCurr=substr($strGB, $i, 2); $intGB=hexdec(bin2hex($strCurr)) - 0x8080; $intStart=1; $intEnd=$intCount; while ($intStart < $intEnd - 1) { // 折半法查找 $intMid=floor(($intStart + $intEnd) / 2); $intOffset=2 + 4 * ($intMid - 1); fseek($fileGBU, $intOffset); $strBuf=fread($fileGBU, 2); $intCode=ord($strBuf{0}) + 256 * ord($strBuf{1}); if ($intGB==$intCode) { $intStart=$intMid; break; } if ($intGB > $intCode) $intStart=$intMid; else $intEnd=$intMid; } $intOffset=2 + 4 * ($intStart - 1); fseek($fileGBU, $intOffset); $strBuf=fread($fileGBU, 2); $intCode=ord($strBuf{0}) + 256 * ord($strBuf{1}); if ($intGB==$intCode) { $strBuf=fread($fileGBU, 2); $intCodeU=ord($strBuf{0}) + 256 * ord($strBuf{1}); $strRet .=u2utf8($intCodeU); } else { $strRet .=""; } $i++; } else { $strRet .=$strGB{$i}; } } return $strRet; } |
把其加到原来的测评程序,对三种方法同时测评2次得到数据(精确到3位小数,单位:秒):
MySQL方法:0.125
文本文件方法:10.873
二进制文件折半法:0.106
MySQL方法:0.102
文本文件方法:10.677
二进制文件折半法:0.092
可见二进制文件折半法还比MySQL法略有优势。但是上述测评都是对短的地理位置进行转码,如果对较长的文本转码又如何呢?我找来5个Blog的RSS 2.0文件,都是GB2312编码。测评三种方法对5个文件编码耗费的时间,2次测量数据如下(精确到3位小数,单位:秒):
MySQL方法:7.206
文本文件方法:0.772
二进制文件折半法:5.022
MySQL方法:7.440
文本文件方法:0.766
二进制文件折半法:5.055
可见对长的文本是用文本文件的方法最优,因为转码对照表读入内存后,转码就可以很高效了。既然如此,我们还可以尝试改进一下,把文本文件方法改为:转码对照表从二进制文件gbu.dat读入内存,而不是文本文件。测评数据如下(精度和单位同上):
从文本文件读入对照表:0.766
从二进制文件读入对照表:0.831
从文本文件读入对照表:0.774
从二进制文件读入对照表:0.833
表明这次改进失败了,从文本文件读入转码对照表更高效。
总结:用PHP对GB编码到UTF-8编码的动态转换,如果每次转换的文本很小,适宜用二进制文件结合折半法转换;如果每次转换的文本较大,适宜用文本文件存储转码对照表,并在转换前一次性把对照表读入内存。
以上所分享的是关于php对gb编码动态转utf-8编码的几种方法评测,下面是编辑为你推荐的有价值的用户互动:
相关问题:求utf8与gb2312字符编码互转的php代码
答:function autoCharset($string, $from='gbk', $to='utf-8') { $from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from; $to = strtoupper($to) == 'UTF8' ? 'utf-8' : $to; if (strtoupper($from) === strtoupper($to) || empty($string) || (i... >>详细
相关问题:PHP如何将utf-8转换成gb2312?请给出具体代码。
答:可以采用编辑器工具进行转换 转换后 html编码代码也要修改为 望采纳 Thx >>详细
相关问题:PHP怎么把经过UTF-8编码的中文字符转换成正常的中文
答:如下: 0 Then If f Then s = s & "%" & Right("00" & Hex(Asc(t)),2) Else s = s & t End If Else If jjjj < 0 Then jjjj = jjjj + &H10000 h = (jjjj And &HFF00) \ &HFF l = jjjj And &HFF s = s & "%" & Hex(h) & "%" & Hex(l) End If Next ... >>详细
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
