GD输出汉字的函数的分析


Posted in PHP onOctober 09, 2006

    很早以前找到一个把GB码转化为UTF-8的函数,配合一个GB到UNICODE的对照表(gb2312.txt),用于在GD中输出汉字。后来发现在欲输出的内容中含有西文字符时,会出现混乱。后来找到了修改后的代码,解决了问题。现将两个函数做一对比分析如下。

首先,这是一个UNICODE到UTF-8编码转换的函数,这一部分修改前后没有变化:
function u2utf8($c)
{
for($i=0;$i<count($c);$i++)
$str="";
if ($c < 0x80) {
$str.=$c;
}
else if ($c < 0x800) {
$str.=(0xC0 | $c>>6);
$str.=(0x80 | $c & 0x3F);
}
else if ($c < 0x10000) {
$str.=(0xE0 | $c>>12);
$str.=(0x80 | $c>>6 & 0x3F);
$str.=(0x80 | $c & 0x3F);
}
else if ($c < 0x200000) {
$str.=(0xF0 | $c>>18);
$str.=(0x80 | $c>>12 & 0x3F);
$str.=(0x80 | $c>>6 & 0x3F);
$str.=(0x80 | $c & 0x3F);
}
return $str;
}

这里完全是按照UTF-8编码的规则,通过判断字符属于不同的UNICODE编码段范围,进行不同的移位和位与操作,以转化为UTF-8编码。关于该规则可参考http://www.utf8.org/上的说明。

这是修改前的GB转化为UTF-8编码的函数,其中调用了上面的u2utf8函数。
function gb2utf8($gb)     /* Program writen by sadly www.phpx.com  */
{
if(!trim($gb))
return $gb;
$filename="gb2312.txt";
$tmp=file($filename);
$codetable=array();
while(list($key,$value)=each($tmp))
$codetable[hexdec(substr($value,0,6))]=substr($value,7,6);
$utf8="";
while($gb)
{
if (ord(substr($gb,0,1))>127)
{
$this=substr($gb,0,2);
$gb=substr($gb,2,strlen($gb));
$utf8.=u2utf8(hexdec($codetable[hexdec(bin2hex($this))-0x8080]));
}
else
{
$gb=substr($gb,1,strlen($gb));
$utf8.=u2utf8(substr($gb,0,1));
}
}

$ret="";
for($i=0;$i<strlen($utf8);$i+=3)
$ret.=chr(substr($utf8,$i,3));

return $ret;
}
函数中while循环部分,把汉字逐个按照“对照表”转化为UNICODE,再通过u2utf8函数转化为UTF-8。但从中可以看出,while循环结束后,又用一个for循环,把每三个字节合成了一个UTF-8字符(见http://www.utf8.org/上的规则说明,每个汉字的UTF-8编码为三字节),没有考虑到其中的西文字符(西文字符的UTF-8编码为一字节)。所以,如果欲输出的内容中不论是开始时出现西文字符,或是汉字当中穿插西文字符,转化为UTF-8后,都会被按照“每三个字节截取”的方式截开,导致乱码。

以下是修改后的函数:
function gb2utf8($gb)    /* Program writen by sadly   modified by agun */
{
if(!trim($gb))
return $gb;
$filename="gb2312.txt";
$tmp=file($filename);
$codetable=array();
while(list($key,$value)=each($tmp))
$codetable[hexdec(substr($value,0,6))]=substr($value,7,6);

$ret="";
$utf8="";
while($gb)
{
if (ord(substr($gb,0,1))>127)
{
$this=substr($gb,0,2);
$gb=substr($gb,2,strlen($gb));
$utf8=u2utf8(hexdec($codetable[hexdec(bin2hex($this))-0x8080]));
for($i=0;$i<strlen($utf8);$i+=3)
$ret.=chr(substr($utf8,$i,3));
}
else
{
$ret.=substr($gb,0,1);
$gb=substr($gb,1,strlen($gb));
}
}
return $ret;
}

修改后的函数将 GB转化为UNICODE、UNICODE转化为UTF-8、几个字节合成一个UTF-8字符,这三个步骤在一个循环里完成,尤其是几个字节合成一个UTF-8字符这一步骤,放在判断了字符属于西文还是属于汉字的条件分支里,据此决定截取一个字节还是三个字节。于是结果正确了!

PHP 相关文章推荐
下载文件的点击数回填
Oct 09 PHP
隐藏你的.php文件的实现方法
Mar 19 PHP
php使用curl访问https示例分享
Jan 17 PHP
php在线解压ZIP文件的方法
Dec 30 PHP
Laravel 5.0 发布 新版本特性详解
Feb 10 PHP
WordPress中限制非管理员用户在文章后只能评论一次
Dec 31 PHP
PHP中strncmp()函数比较两个字符串前2个字符是否相等的方法
Jan 07 PHP
在Win2003(64位)中配置IIS6+PHP5.2.17+MySQL5.5的运行环境
Apr 04 PHP
PHP单态模式简单用法示例
Nov 16 PHP
深入解析PHP中SESSION反序列化机制
Mar 01 PHP
Laravel中正确地返回HTTP状态码方法示例
Sep 10 PHP
laravel框架的安装与路由实例分析
Oct 11 PHP
类的另类用法--数据的封装
Oct 09 #PHP
最小化数据传输――在客户端存储数据
Oct 09 #PHP
网站加速 PHP 缓冲的免费实现方法
Oct 09 #PHP
Windows下PHP的任意文件执行漏洞
Oct 09 #PHP
通过对服务器端特性的配置加强php的安全
Oct 09 #PHP
用Zend Encode编写开发PHP程序
Oct 09 #PHP
在php中使用sockets:从新闻组中获取文章
Oct 09 #PHP
You might like
php设置页面超时时间解决方法
2015/09/22 PHP
PHP面向对象程序设计子类扩展父类(子类重新载入父类)操作详解
2019/06/14 PHP
通过JAVAScript实现页面自适应
2007/01/19 Javascript
JS网络游戏-(模拟城市webgame)提供的一些例子下载
2007/10/14 Javascript
js innerHTML 的一些问题的解决方法
2008/06/22 Javascript
运用JQuery的toggle实现网页加载完成自动弹窗
2014/03/18 Javascript
中文输入法不触发onkeyup事件的解决办法
2014/07/09 Javascript
JavaScript中调用函数的4种方式代码实例
2015/07/08 Javascript
javascript动画算法实例分析
2015/07/31 Javascript
Vue.js自定义指令的用法与实例解析
2017/01/18 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
2017/02/03 Javascript
js字符串与Unicode编码互相转换
2017/05/17 Javascript
基于对象合并功能的实现示例
2017/10/10 Javascript
「中高级前端面试」JavaScript手写代码无敌秘籍(推荐)
2019/04/08 Javascript
微信小程序Echarts覆盖正常组件问题解决
2019/07/13 Javascript
JavaScript 截取字符串代码实例
2019/09/05 Javascript
python异常和文件处理机制详解
2016/07/19 Python
总结用Pdb库调试Python的方式及常用的命令
2016/08/18 Python
解决python中使用PYQT时中文乱码问题
2019/06/17 Python
python单线程下实现多个socket并发过程详解
2019/07/27 Python
解决Tensorflow sess.run导致的内存溢出问题
2020/02/05 Python
Python实现结构体代码实例
2020/02/10 Python
python numpy库np.percentile用法说明
2020/06/08 Python
前后端结合实现amazeUI分页效果
2020/08/21 HTML / CSS
eBay德国站:eBay.de
2017/09/14 全球购物
造型师求职自荐信
2013/09/27 职场文书
个人简历自我评价
2014/01/06 职场文书
三八妇女节活动总结
2014/05/04 职场文书
法律专业自荐信
2014/06/03 职场文书
乡镇领导班子批评与自我批评材料
2014/09/23 职场文书
教师学习八项规定六项禁令思想汇报
2014/09/27 职场文书
2014年财务部工作总结
2014/11/11 职场文书
意向协议书
2015/01/27 职场文书
2015年中学体育教师工作总结
2015/10/23 职场文书
详解python网络进程
2021/06/15 Python
Java实现扫雷游戏详细代码讲解
2022/05/25 Java/Android