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中HTTP方式下的Gzip压缩传输方法举偶
Feb 15 PHP
PHP 数字左侧自动补0
Mar 31 PHP
PHP 文本文章分页代码 按标记或长度(不涉及数据库)
Jun 07 PHP
PHP FATAL ERROR: CALL TO UNDEFINED FUNCTION BCMUL()解决办法
May 04 PHP
Codeigniter中禁止A Database Error Occurred错误提示的方法
Jun 12 PHP
PHP中Fatal error session_start()错误解决步骤
Aug 05 PHP
教你如何开启shopnc b2b2c 伪静态
Oct 21 PHP
PHP实现模仿socket请求返回页面的方法
Nov 04 PHP
WIFI万能钥匙密码查询接口实例
Sep 28 PHP
对比PHP对MySQL的缓冲查询和无缓冲查询
Jul 01 PHP
PHP判断数组是否为空的常用方法(五种方法)
Feb 08 PHP
PHP中通过getopt解析GNU C风格命令行选项
Nov 18 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中取得文件的后缀名?
2012/02/20 PHP
浅析php变量作用域的一些问题
2013/08/08 PHP
php 邮件发送问题解决
2014/03/22 PHP
ThinkPHP3.1.3版本新特性概述
2014/06/19 PHP
php中的四舍五入函数代码(floor函数、ceil函数、round与intval)
2014/07/14 PHP
Yii快速入门经典教程
2015/12/28 PHP
PHP基本语法实例总结
2016/09/09 PHP
微信第三方登录(原生)demo【必看篇】
2017/05/26 PHP
javascript中的prototype属性实例分析说明
2010/08/09 Javascript
基于JQuery的一个简单的鼠标跟随提示效果
2010/09/23 Javascript
javascript:void(0)点击登录没反应怎么解决
2015/11/13 Javascript
JavaScript的Backbone.js框架的一些使用建议整理
2016/02/14 Javascript
用iframe实现不刷新整个页面上传图片的实例
2016/11/18 Javascript
js验证手机号、密码、短信验证码代码工具类
2020/06/24 Javascript
jQuery加载及解析XML文件的方法实例分析
2017/01/22 Javascript
docker中编译nodejs并使用nginx启动
2017/06/23 NodeJs
详解react-native-fs插件的使用以及遇到的坑
2017/09/12 Javascript
php结合js实现多条件组合查询
2019/05/28 Javascript
JavaScript实现背景自动切换小案例
2019/09/27 Javascript
JavaScript 空间坐标的使用
2020/08/19 Javascript
原生js实现自定义难度的扫雷游戏
2021/01/22 Javascript
python连接字符串的方法小结
2015/07/13 Python
python3.5 + PyQt5 +Eric6 实现的一个计算器代码
2017/03/11 Python
Django缓存系统实现过程解析
2019/08/02 Python
python给指定csv表格中的联系人群发邮件(带附件的邮件)
2019/12/31 Python
Python 写了个新型冠状病毒疫情传播模拟程序
2020/02/14 Python
Python如何给你的程序做性能测试
2020/07/29 Python
Pycharm新手使用教程(图文详解)
2020/09/17 Python
详解Python爬虫爬取博客园问题列表所有的问题
2021/01/18 Python
Melissa鞋马来西亚官方网站:MDreams马来西亚
2018/04/05 全球购物
BIFFI美国站:意大利BIFFI BOUTIQUES豪华多品牌时装零售公司
2020/02/11 全球购物
十佳护士获奖感言
2014/02/18 职场文书
师德培训心得体会2016
2016/01/09 职场文书
Python基础之元组与文件知识总结
2021/05/19 Python
Springboot集成阿里云OSS上传文件系统教程
2021/06/28 Java/Android
MySQL如何修改字段类型和字段长度
2022/06/10 MySQL