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 相关文章推荐
来自phpguru得Php Cache类源码
Apr 15 PHP
队列在编程中的实际应用(php)
Sep 04 PHP
利用php+mysql来做一个功能强大的在线计算器
Oct 12 PHP
批量修改RAR文件注释的php代码
Nov 20 PHP
PHP中读写文件实现代码
Oct 20 PHP
PhpMyAdmin出现export.php Missing parameter: what /export_type错误解决方法
Aug 09 PHP
PHP开发中常见的安全问题详解和解决方法(如Sql注入、CSRF、Xss、CC等)
Apr 21 PHP
PHP利用func_get_args和func_num_args函数实现函数重载实例
Nov 12 PHP
PHP中__autoload和Smarty冲突的简单解决方法
Apr 08 PHP
php实现的网页版剪刀石头布游戏示例
Nov 25 PHP
PHP面向对象程序设计之对象生成方法详解
Dec 02 PHP
PHP简单实现防止SQL注入的方法
Mar 13 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
星际争霸 Starcraft 发展史
2020/03/14 星际争霸
短波的认识
2021/03/01 无线电
php一些错误处理的方法与技巧总结
2013/08/10 PHP
ThinkPHP使用心得分享-分页类Page的用法
2014/05/15 PHP
PHP+memcache实现消息队列案例分享
2014/05/21 PHP
PHP记录搜索引擎蜘蛛访问网站足迹的方法
2015/04/15 PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
2017/11/17 PHP
PHP fprintf()函数用法讲解
2019/02/16 PHP
浅谈laravel框架sql中groupBy之后排序的问题
2019/10/17 PHP
Javascript 继承机制的实现
2009/08/12 Javascript
Jquery ajaxsubmit上传图片实现代码
2010/11/04 Javascript
javascript 内存回收机制理解
2011/01/17 Javascript
控制页面按钮在后台执行期间不重复提交的JS方法
2013/06/24 Javascript
javascript的内存管理详解
2013/08/07 Javascript
jQuery Easyui 验证两次密码输入是否相等
2016/05/13 Javascript
JavaScript实现横线提示输入验证码随输入验证码输入消失的方法
2016/09/24 Javascript
Nodejs基于LRU算法实现的缓存处理操作示例
2017/03/17 NodeJs
ES6新特性之数组、Math和扩展操作符用法示例
2017/04/01 Javascript
vue轮播图插件vue-concise-slider的使用
2018/03/13 Javascript
对Vue- 动态元素属性及v-bind和v-model的区别详解
2018/08/27 Javascript
autojs 蚂蚁森林能量自动拾取即给指定好友浇水的实现方法
2020/05/03 Javascript
Vue 封装防刷新考试倒计时组件的实现
2020/06/05 Javascript
对vuex中store和$store的区别说明
2020/07/24 Javascript
ubuntu系统下使用pm2设置nodejs开机自启动的方法
2018/05/12 NodeJs
Tensorflow卷积实现原理+手写python代码实现卷积教程
2020/05/22 Python
python tkiner实现 一个小小的图片翻页功能的示例代码
2020/06/24 Python
Python爬虫中Selenium实现文件上传
2020/12/04 Python
YesStyle美国/全球:购买亚洲时装、美容化妆品和生活百货
2017/01/16 全球购物
大学生写自荐信的技巧
2014/01/08 职场文书
金融系毕业生自荐书
2014/07/08 职场文书
学校组织向国旗敬礼活动方案(中小学适用)
2014/09/27 职场文书
单位法人授权委托书范本
2014/10/09 职场文书
2014年医务科工作总结
2014/12/18 职场文书
写给导师的自荐信
2015/03/06 职场文书
班主任经验交流心得体会
2015/11/02 职场文书
python批量更改目录名/文件名的方法
2021/04/18 Python