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获取文件后缀名的三个函数
Oct 15 PHP
PHP中ini_set和ini_get函数的用法小结
Feb 18 PHP
php接口和抽象类使用示例详解
Mar 02 PHP
PHP实现自动登入google play下载app report的方法
Sep 23 PHP
详谈PHP文件目录基础操作
Nov 11 PHP
javascript some()函数用法详解
Nov 13 PHP
php将textarea数据提交到mysql出现很多空格的解决方法
Dec 19 PHP
PHP递归遍历多维数组实现无限分类的方法
May 06 PHP
php+ajax实现仿百度查询下拉内容功能示例
Oct 20 PHP
PHP中in_array的隐式转换的解决方法
Mar 06 PHP
Linux下 php7安装redis的方法
Nov 01 PHP
PHP实现获取毫秒时间戳的方法【使用microtime()函数】
Mar 01 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制作的意见反馈表源码
2007/03/11 PHP
PHP 数字左侧自动补0
2008/03/31 PHP
PHP常用正则表达式集锦
2014/08/17 PHP
php通过递归方式复制目录和子目录的方法
2015/03/13 PHP
Linux系统下使用XHProf和XHGui分析PHP运行性能
2015/12/08 PHP
PHP文字转图片功能原理与实现方法分析
2017/08/31 PHP
php删除一个路径下的所有文件夹和文件的方法
2018/02/07 PHP
Javascript中Eval函数的使用说明
2008/10/11 Javascript
jMessageBox 基于jQuery的窗口插件
2009/12/09 Javascript
在JavaScript中实现类的方式探讨
2013/08/28 Javascript
分享两款带遮罩的jQuery弹出框
2015/12/30 Javascript
Angularjs中$http以post请求通过消息体传递参数的实现方法
2016/08/05 Javascript
JS 实现Base64编码与解码实例详解
2016/11/07 Javascript
VUE JS 使用组件实现双向绑定的示例代码
2017/01/10 Javascript
基于BootStrap实现简洁注册界面
2017/07/20 Javascript
JS实现登录页密码的显示和隐藏功能
2017/12/06 Javascript
在vue中使用echarts图表实例代码详解
2018/10/22 Javascript
详解Vue template 如何支持多个根结点
2020/02/10 Javascript
videocapture库制作python视频高速传输程序
2013/12/23 Python
python实现文本去重且不打乱原本顺序
2016/01/26 Python
使用pandas read_table读取csv文件的方法
2018/07/04 Python
python2和python3在处理字符串上的区别详解
2019/05/29 Python
深入浅析Python中的迭代器
2019/06/04 Python
Python企业编码生成系统总体系统设计概述
2019/07/26 Python
python异步编程 使用yield from过程解析
2019/09/25 Python
TensorFlow Saver:保存和读取模型参数.ckpt实例
2020/02/10 Python
selenium+headless chrome爬虫的实现示例
2021/01/08 Python
Canvas与图片压缩的示例代码
2017/11/28 HTML / CSS
AmazeUI 评论列表的实现示例
2020/08/13 HTML / CSS
毕业生简单求职信
2013/11/19 职场文书
小学信息技术教学反思
2014/02/10 职场文书
运动会通讯稿200字
2015/07/20 职场文书
追悼会家属答谢词
2015/09/29 职场文书
基于python制作简易版学生信息管理系统
2021/04/20 Python
Python爬虫基础之爬虫的分类知识总结
2021/05/13 Python
关于JavaScript轮播图的实现
2021/11/20 Javascript