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 相关文章推荐
Apache2 httpd.conf 中文版
Nov 17 PHP
PHP session有效期问题
Apr 26 PHP
PHP 获取远程文件内容的函数代码
Mar 24 PHP
jQuery 源码分析笔记
May 25 PHP
用PHP+MySQL搭建聊天室功能实例代码
Aug 20 PHP
php实现监听事件
Nov 06 PHP
Yii入门教程之Yii安装及hello world
Nov 25 PHP
php rmdir使用递归函数删除非空目录实例详解
Oct 20 PHP
Ubuntu彻底删除PHP7.0的方法
Jul 27 PHP
PHP集成环境XAMPP的安装与配置
Nov 13 PHP
laravel 解决路由除了根目录其他都404的问题
Oct 18 PHP
Laravel框架源码解析之反射的使用详解
May 14 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无敌近乎加密方式!
2010/07/17 PHP
Zend Framework入门知识点小结
2016/03/19 PHP
php的instanceof和判断闭包Closure操作示例
2020/01/26 PHP
jQuery+CSS 实现的超Sexy下拉菜单
2010/01/17 Javascript
JS控制显示隐藏兼容问题(IE6、IE7、IE8)
2010/04/01 Javascript
非主流的textarea自增长实现js代码
2011/12/20 Javascript
JQUERY 实现窗口滚动搜索框停靠效果(类似滚动停靠)
2013/03/27 Javascript
JavaScript中json使用自己总结
2013/08/13 Javascript
jquery parent和parents的区别分析
2013/10/02 Javascript
jQuery插件pagewalkthrough实现引导页效果
2015/07/05 Javascript
jquery实现树形菜单完整代码
2015/12/29 Javascript
理解Javascript图片预加载
2016/02/23 Javascript
浅谈js中子页面父页面方法 变量相互调用
2016/08/04 Javascript
javascript DOM的详解及实例代码
2017/03/06 Javascript
微信小程序 弹窗输入组件的实现解析
2019/08/12 Javascript
JS通用方法触发点击事件代码实例
2020/02/17 Javascript
python字符类型的一些方法小结
2016/05/16 Python
itchat和matplotlib的结合使用爬取微信信息的实例
2017/08/25 Python
Python使用numpy实现BP神经网络
2018/03/10 Python
python+opencv识别图片中的圆形
2020/03/25 Python
Python列表list排列组合操作示例
2018/12/18 Python
浅谈python之高阶函数和匿名函数
2019/03/21 Python
python 装饰器的使用示例
2020/10/10 Python
Bodum官网:咖啡和茶壶、玻璃器皿、厨房电器等
2018/08/01 全球购物
为什么需要版本控制
2016/10/28 面试题
追悼会主持词
2014/03/20 职场文书
活动策划求职信模板
2014/04/21 职场文书
2014年社会实践活动总结范文
2014/04/29 职场文书
企业读书活动总结
2014/06/30 职场文书
门面房租房协议书
2014/08/20 职场文书
2015年街道除四害工作总结
2015/05/15 职场文书
生日寿星公答谢词
2015/09/29 职场文书
学习焦裕禄先进事迹心得体会
2016/01/23 职场文书
2019餐饮行业创业计划书!
2019/06/27 职场文书
元素水平垂直居中的方式
2021/03/31 HTML / CSS
Go语言特点及基本数据类型使用详解
2022/03/21 Golang