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 相关文章推荐
文件上传的实现
Oct 09 PHP
php自定义函数之递归删除文件及目录
Aug 08 PHP
php统计文件大小,以GB、MB、KB、B输出
May 29 PHP
解析PHPExcel使用的常用说明以及把PHPExcel整合进CI框架的介绍
Jun 24 PHP
11个PHPer必须要了解的编程规范
Sep 22 PHP
php生成rss类用法实例
Apr 14 PHP
使用PHP生成二维码的方法汇总
Jul 22 PHP
PHP get_html_translation_table()函数用法讲解
Feb 16 PHP
基于laravel where的高级使用方法
Oct 10 PHP
laravel 中某一字段自增、自减的例子
Oct 11 PHP
laravel unique验证、确认密码confirmed验证以及密码修改验证的方法
Oct 16 PHP
PHP PDO和消息队列的个人理解与应用实例分析
Nov 25 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
实用函数7
2007/11/08 PHP
php定时执行任务设置详解
2015/02/06 PHP
PHP+APACHE实现网址伪静态
2015/02/22 PHP
Laravel框架实现修改登录和注册接口数据返回格式的方法
2018/08/17 PHP
PHP hebrev()函数用法讲解
2019/02/21 PHP
PHP+redis实现微博的拉模型案例详解
2019/07/10 PHP
php ZipArchive实现多文件打包下载实例
2019/10/31 PHP
Yii框架应用组件用法实例分析
2020/05/15 PHP
解决IE下select标签innerHTML插入option的BUG(兼容IE,FF,Opera,Chrome,Safari)
2010/05/13 Javascript
jQuery技巧总结
2011/01/01 Javascript
jqTransform form表单美化插件使用方法
2012/07/05 Javascript
javascript面向对象快速入门实例
2015/01/13 Javascript
JavaScript使用shift方法移除素组第一个元素实例分析
2015/04/06 Javascript
jQuery实现鼠标滚动图片延迟加载效果附源码下载
2016/06/28 Javascript
详解AngularJS中ng-src指令的使用
2016/09/07 Javascript
详解Vue.js入门环境搭建
2017/03/17 Javascript
完美解决axios在ie下的兼容性问题
2018/03/05 Javascript
Node.js对MongoDB进行增删改查操作的实例代码
2019/04/18 Javascript
jquery实现动态创建form并提交的方法示例
2019/05/27 jQuery
vue解决使用$http获取数据时报错的问题
2019/10/30 Javascript
vue实现轮播图帧率播放
2021/01/26 Vue.js
javascript实现倒计时关闭广告
2021/02/09 Javascript
[01:45]绝对公平!DOTA2队长征召模式详解
2014/04/25 DOTA
Django自定义分页与bootstrap分页结合
2021/02/22 Python
在pytorch中为Module和Tensor指定GPU的例子
2019/08/19 Python
在tensorflow以及keras安装目录查询操作(windows下)
2020/06/19 Python
PyCharm 2020.2 安装详细教程
2020/09/25 Python
美国单身专业人士在线约会网站:EliteSingles
2019/03/19 全球购物
巴西购物网站:Onofre Agora
2020/06/08 全球购物
请解释流与文件有什么不同
2016/07/29 面试题
params有什么用
2016/03/01 面试题
学校校庆演讲稿
2014/05/22 职场文书
校园学雷锋广播稿
2014/10/08 职场文书
三好学生主要事迹材料
2015/11/03 职场文书
ajax请求前端跨域问题原因及解决方案
2021/10/16 Javascript
PHP 时间处理类Carbon
2022/05/20 PHP