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 相关文章推荐
Ajax+PHP 边学边练之四 表单
Nov 27 PHP
php将数据库中所有内容生成静态html文档的代码
Apr 12 PHP
php魔术方法与魔术变量、内置方法与内置变量的深入分析
Jun 03 PHP
php 备份数据库代码(生成word,excel,json,xml,sql)
Jun 23 PHP
解析php dirname()与__FILE__常量的应用
Jun 24 PHP
php number_format() 函数通过千位分组来格式化数字的实现代码
Aug 06 PHP
Yii2实现log输出到file及database的方法
Nov 12 PHP
ThinkPHP中类的构造函数_construct()与_initialize()的区别详解
Mar 13 PHP
php app支付宝回调(异步通知)详解
Jul 25 PHP
php使用socket调用http和smtp协议实例小结
Jul 26 PHP
Laravel手动返回错误码示例
Oct 22 PHP
laravel 创建命令行命令的图文教程
Oct 23 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正则表达式中修饰符/i, /is, /s, /isU
2014/10/21 PHP
Sample script that deletes a SQL Server database
2007/06/16 Javascript
js类中获取外部函数名的方法与代码
2007/09/12 Javascript
用JavaScript调用WebService的示例
2008/04/07 Javascript
jQuery中判断一个元素是否为另一个元素的子元素(或者其本身)
2012/03/21 Javascript
javascript五图轮播切换实用版
2012/08/17 Javascript
js仿百度贴吧验证码特效实例代码
2014/01/16 Javascript
使表格的标题列可左右拉伸jquery插件封装
2014/11/24 Javascript
使用js实现数据格式化
2014/12/03 Javascript
浅析JavaScript声明变量
2015/12/21 Javascript
Javascript中关于Array.filter()的妙用详解
2016/12/04 Javascript
jQuery选择器实例应用
2017/01/05 Javascript
jQuery编写设置和获取颜色的插件
2017/01/09 Javascript
解决BootStrap Fileinput手机图片上传显示旋转问题
2017/06/01 Javascript
浅谈Angular4中常用管道
2017/09/27 Javascript
浅谈laytpl 模板空值显示null的解决方法及简单的js表达式
2019/09/19 Javascript
Vue实现商品飞入购物车效果(电商项目)
2019/11/26 Javascript
微信小程序点击滚动到指定位置的实现
2020/05/22 Javascript
手把手带你搭建一个node cli的方法示例
2020/08/07 Javascript
Python之re操作方法(详解)
2017/06/14 Python
Python3 Post登录并且保存cookie登录其他页面的方法
2018/12/28 Python
python控制nao机器人身体动作实例详解
2019/04/29 Python
Python使用itchat模块实现群聊转发,自动回复功能示例
2019/08/26 Python
Python如何通过Flask-Mail发送电子邮件
2020/01/29 Python
python模拟预测一下新型冠状病毒肺炎的数据
2020/02/01 Python
Django中modelform组件实例用法总结
2020/02/10 Python
python爬虫请求头的使用
2020/12/01 Python
使用python操作lmdb对数据读取的实例
2020/12/11 Python
自我鉴定范文300字
2013/10/01 职场文书
《晏子使楚》教学反思
2014/02/08 职场文书
大学生通用个人的自我评价
2014/02/10 职场文书
工商治理实习生的自我评价分享
2014/02/20 职场文书
学校课外活动总结
2014/05/08 职场文书
党员年终个人总结
2015/02/14 职场文书
初中班干部工作总结
2015/08/10 职场文书
中国十大神话动漫电影排行榜 哪吒登顶 白蛇缘起排第七
2022/03/21 国漫