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 相关文章推荐
php取整函数ceil,floo,round的用法及介绍
Aug 31 PHP
Discuz批量替换帖子内容的方法(使用SQL更新数据库)
Jun 23 PHP
php批量删除数据库下指定前缀的表以prefix_为例
Aug 24 PHP
PHP字符串word末字符实现大小写互换的方法
Nov 10 PHP
php一个文件搞定微信jssdk配置
Dec 12 PHP
php json中文编码为null的解决办法
Dec 14 PHP
PHP实现简单计算器小程序
Aug 28 PHP
统计PHP目录中的文件数方法
Mar 05 PHP
针对PHP开发安全问题的相关总结
Mar 22 PHP
PHP实现与java 通信的插件使用教程
Aug 11 PHP
php实现简单的守护进程创建、开启与关闭操作
Aug 13 PHP
php使用json-schema模块实现json校验示例
Sep 28 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判断服务器是否支持Gzip压缩功能
2013/09/24 PHP
详解PHP中的PDO类
2015/07/06 PHP
PHP快速排序quicksort实例详解
2016/09/28 PHP
Laravel数据库读写分离配置的方法
2019/10/13 PHP
PHP实现获取文件mime类型多种方法解析
2020/05/28 PHP
Javascript 获取链接(url)参数的方法
2009/02/15 Javascript
utf-8编码引起js输出中文乱码的解决办法
2010/06/23 Javascript
Document.body.scrollTop的值总为零的快速解决办法
2016/06/09 Javascript
js获取浏览器高度 窗口高度 元素尺寸 偏移属性的方法
2016/11/21 Javascript
JS解决移动web开发手机输入框弹出的问题
2017/03/31 Javascript
详解Angular路由之路由守卫
2018/05/10 Javascript
angular6.0使用教程之父组件通过url传递id给子组件的方法
2018/06/30 Javascript
三种Webpack打包方式(小结)
2018/09/19 Javascript
js对象属性名驼峰式转下划线的实例代码
2020/09/17 Javascript
如何管理Vue中的缓存页面
2021/02/06 Vue.js
[00:30]塑造者的传承礼包-戴泽“暗影之焰”套装展示视频
2014/04/04 DOTA
[27:53]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS iG
2014/05/26 DOTA
[54:57]DOTA2-DPC中国联赛定级赛 Aster vs DLG BO3第二场 1月8日
2021/03/11 DOTA
Python实现给文件添加内容及得到文件信息的方法
2015/05/28 Python
Python使用arrow库优雅地处理时间数据详解
2017/10/10 Python
Python操作Oracle数据库的简单方法和封装类实例
2018/05/07 Python
Python3.7 读取音频根据文件名生成脚本的代码
2020/04/07 Python
django模板获取list中指定索引的值方式
2020/05/14 Python
Python批量获取并保存手机号归属地和运营商的示例
2020/10/09 Python
Python爬虫破解登陆哔哩哔哩的方法
2020/11/17 Python
加拿大消费电子和手机购物网站:The Source
2017/01/28 全球购物
英国独特家具和家庭用品购物网站:Cuckooland
2020/08/30 全球购物
计算机维护专业推荐信
2014/02/27 职场文书
如何写好自荐信
2014/04/07 职场文书
副主任竞聘演讲稿
2014/08/18 职场文书
2014年远程教育工作总结
2014/12/09 职场文书
2014年办公室文秘工作总结
2014/12/09 职场文书
初二物理教学反思
2016/02/19 职场文书
企业内部管理控制:采购授权审批制度范本
2020/01/19 职场文书
使用CSS实现黑白格背景效果
2022/06/01 HTML / CSS
5个实用的JavaScript新特性
2022/06/16 Javascript