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 相关文章推荐
DISCUZ 论坛管理员密码忘记的解决方法
May 14 PHP
深入理解PHP原理之异常机制
Aug 21 PHP
php对包含html标签的字符串进行截取的函数分享
Jun 19 PHP
PHP中使用CURL模拟登录并获取数据实例
Jul 01 PHP
Zend Framework 2.0事件管理器(The EventManager)入门教程
Aug 11 PHP
php通过记录IP来防止表单重复提交方法分析
Dec 16 PHP
php二维数组合并及去重复的方法
Mar 04 PHP
php正则替换处理HTML页面的方法
Jun 17 PHP
PHP实现的构造sql语句类实例
Feb 03 PHP
php处理抢购类功能的高并发请求
Feb 08 PHP
php app支付宝回调(异步通知)详解
Jul 25 PHP
PHP容器类的两种实现方式示例
Jul 24 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
截获网站title标签之家内容的例子
2006/10/09 PHP
php设计模式 Interpreter(解释器模式)
2011/06/26 PHP
php循环创建目录示例分享(php创建多级目录)
2014/03/04 PHP
php图片的二进制转换实现方法
2014/12/15 PHP
php实现两个数组相加的方法
2015/02/17 PHP
Thinkphp结合AJAX长轮询实现PC与APP推送详解
2017/07/31 PHP
Laravel框架FormRequest中重写错误处理的方法
2019/02/18 PHP
jquery获取tr并更改tr内容示例代码
2014/02/13 Javascript
js完美解决IE6不支持position:fixed的bug
2015/04/24 Javascript
使用RequireJS库加载JavaScript模块的实例教程
2016/06/06 Javascript
canvas实现图像布局填充功能
2017/02/06 Javascript
使用angular帮你实现拖拽的示例
2017/07/05 Javascript
JS实现Cookie读、写、删除操作工具类示例
2018/08/28 Javascript
详解JavaScript作用域和作用域链
2019/03/19 Javascript
vue中$refs, $emit, $on, $once, $off的使用详解
2019/05/26 Javascript
[01:07:15]DOTA2-DPC中国联赛 正赛 DLG vs XG BO3 第二场 1月25日
2021/03/11 DOTA
python 实现文件的递归拷贝实现代码
2012/08/02 Python
复习Python中的字符串知识点
2015/04/14 Python
python批量添加zabbix Screens的两个脚本分享
2017/01/16 Python
解决nohup重定向python输出到文件不成功的问题
2018/05/11 Python
python opencv实现图片旋转矩形分割
2018/07/26 Python
Python Django 封装分页成通用的模块详解
2019/08/21 Python
使用Python3 poplib模块删除服务器多天前的邮件实现代码
2020/04/24 Python
基于python实现简单C/S模式代码实例
2020/09/14 Python
使用Python绘制台风轨迹图的示例代码
2020/09/21 Python
html5 迷宫游戏(碰撞检测)实例一
2013/07/25 HTML / CSS
豪华复古化妆:Besame Cosmetics
2019/09/06 全球购物
瀑布模型都有哪些优缺点
2014/06/23 面试题
土木工程建筑专业毕业生求职信
2013/10/21 职场文书
护理实习自我鉴定
2013/12/14 职场文书
运动会拉拉队口号
2014/06/09 职场文书
领导干部群众路线剖析材料
2014/10/09 职场文书
上市公司董事长岗位职责
2015/04/16 职场文书
一小时学会TensorFlow2之基本操作2实例代码
2021/09/04 Python
win10忘记pin密码登录不了怎么办?win10忘记pin密码登不进去的解决方法
2022/07/07 数码科技
VUE递归树形实现多级列表
2022/07/15 Vue.js