PHP如何实现Unicode和Utf-8编码相互转换


Posted in PHP onJuly 29, 2015

最近恰好要用到unicode编码的转换,就去查了一下php的库函数,居然没找到一个函数可以对字符串进行Unicode的编码和解码!也罢,找不到的话就自己实现一下了。。。
Unicode和Utf-8编码的区别

Unicode是一个字符集,而UTF-8是Unicode的其中一种,Unicode是定长的都为双字节,而UTF-8是可变的,对于汉字来说Unicode占有的字节比UTF-8占用的字节少1个字节。Unicode为双字节,而UTF-8中汉字占三个字节。
UTF-8编码字符理论上可以最多到6个字节长,然而16位BMP(Basic Multilingual Plane)字符最多只用到3字节长。下面看一下UTF-8编码表:

U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

xxx 的位置由字符编码数的二进制表示的位填入, 越靠右的 x 具有越少的特殊意义,只用最短的那个足够表达一个字符编码数的多字节串。 注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目。而第一行中以0开头,是为了兼容ASCII编码,为一个字节,第二行就为双字节字符串,第三行为3字节,如汉字就属于这种,以此类推。(个人认为:其实我们可以简单的把前面的1的个数看成字节数)

Unicode怎么转换成Utf-8呢

为了要将Unicode转换为UTF-8,当然要知道他们的区别到底在什么地方。下面来看一下,在Unicode中的编码是怎样转换成UTF-8的,在UTF-8中,如果一个字符的字节小于0x80(128)则为ASCII字符,占一个字节,可以不用转换,因为UTF-8兼容ASCII编码。假如在Unicode中汉字“你”的编码为“u4F60”,把它转换为二进制为100111101100000,然后按照UTF-8的方法进行转换。可以将Unicode二进制从低位往高位取出二进制数字,每次取6位,如上述的二进制就可以分别取出为如下所示的格式,前面按格式填补,不足8位用0填补。

unicode: 100111101100000                   4F60

utf-8:    11100100,10111101,10100000       E4BDA0

从上面就可以很直观的看出Unicode到UTF-8之间的转换,当然知道了UTF-8的格式后,就可以进行逆运算,就是按照格式把它在二进制中的相应位置上取出,然后在转换就是所得到的Unicode字符了(这个运算可以通过“位移”来完成)。如上述的“你”的转换,由于其值大于0x800小于0x10000,因此可以判断为三字节存储,则最高位需要向右移“12”位再根据三字节格式的最高位为11100000(0xE0)求或(|)就可以得到最高位的值了。同理第二位则是右移“6”位,则还剩下最高位和第二位的二进制值,可以通过与111111(0x3F)求按位于(&)操作,再和11000000(0x80)求或(|)。第三位就不用移位了,只要直接取最后六位(与111111(ox3F)取&),在与11000000(0x80)求或(|)。

Utf-8怎么逆转回Unicode呢

当然在UTF-8到Unicode的转换也是通过移位等来完成的,就是把UTF-8那些格式相应的位置的二进制数给揪出来。在上述例子中“你”为三个字节,因此要每个字节进行处理,有高位到低位进行处理。在UTF-8中“你”为11100100,10111101,10100000。从高位起即第一个字节11100100就是把其中的"0100"给取出来,这个很简单只要和11111(0x1F)取与(&),由三字节可以得知最到位肯定位于12位之前,因为每次取六位。所以还要将得到的结果左移12位,最高位也就这样完成了0100,000000,000000。而第二位则是要把“111101”给取出来,则只需将第二字节10111101和111111(0x3F)取与(&)。在将所得到的结果左移6位与最高字节所得的结果取或(|),第二位就这样完成了,得到的结果为0100,111101,000000。以此类推最后一位直接与111111(0x3F)取与(&),再与前面所得的结果取或(|)即可得到结果0100,111101,100000。

PHP代码实现: 

/**
 * utf8字符转换成Unicode字符
 * @param [type] $utf8_str Utf-8字符
 * @return [type]      Unicode字符
 */
function utf8_str_to_unicode($utf8_str) {
  $unicode = 0;
  $unicode = (ord($utf8_str[0]) & 0x1F) << 12;
  $unicode |= (ord($utf8_str[1]) & 0x3F) << 6;
  $unicode |= (ord($utf8_str[2]) & 0x3F);
  return dechex($unicode);
}

/**
 * Unicode字符转换成utf8字符
 * @param [type] $unicode_str Unicode字符
 * @return [type]       Utf-8字符
 */
function unicode_to_utf8($unicode_str) {
  $utf8_str = '';
  $code = intval(hexdec($unicode_str));
  //这里注意转换出来的code一定得是整形,这样才会正确的按位操作
  $ord_1 = decbin(0xe0 | ($code >> 12));
  $ord_2 = decbin(0x80 | (($code >> 6) & 0x3f));
  $ord_3 = decbin(0x80 | ($code & 0x3f));
  $utf8_str = chr(bindec($ord_1)) . chr(bindec($ord_2)) . chr(bindec($ord_3));
  return $utf8_str;
}

测试一下了

$utf8_str = '我';

//这是汉字“你”的Unicode编码
$unicode_str = '4f6b';

//输出 6211
echo utf8_str_to_unicode($utf8_str) . "<br/>";

//输出汉字“你”
echo unicode_str_to_utf8($unicode_str);

以上这些转换是针对中文汉字(非ASCII)的测试,并且只支持单个字符【一个完整的utf8字符或是一个完整的Unicode字符】互相转换,希望对大家的学习有所帮助。

PHP 相关文章推荐
深入eAccelerator与memcached的区别详解
Jun 06 PHP
如何在PHP中使用正则表达式进行查找替换
Jun 13 PHP
YII实现分页的方法
Jul 09 PHP
ThinkPHP整合百度Ueditor图文教程
Oct 21 PHP
ThinkPHP中__initialize()和类的构造函数__construct()用法分析
Nov 29 PHP
Zend Framework教程之Zend_Form组件实现表单提交并显示错误提示的方法
Mar 21 PHP
PHP 芝麻信用接入的注意事项
Dec 01 PHP
php正则判断是否为合法身份证号的方法
Mar 16 PHP
PHP实现的分页类定义与用法示例
Jul 05 PHP
PHP实现找出有序数组中绝对值最小的数算法分析
Aug 07 PHP
PHP实现的简单sha1加密功能示例
Aug 27 PHP
Laravel框架搜索分页功能示例
Feb 01 PHP
PHP模拟QQ登录的方法
Jul 29 #PHP
PHP实现动态web服务器方法
Jul 29 #PHP
php调用淘宝开放API实现根据卖家昵称获取卖家店铺ID的方法
Jul 29 #PHP
php简单防盗链实现方法
Jul 29 #PHP
如何用PHP来实现一个动态Web服务器
Jul 29 #PHP
php实现过滤字符串中的中文和数字实例
Jul 29 #PHP
php实现XSS安全过滤的方法
Jul 29 #PHP
You might like
IIS环境下快速安装、配置和调试PHP5.2.0
2006/12/17 PHP
thinkphp3.0输出重复两次的解决方法
2014/12/19 PHP
thinkphp jquery实现图片上传和预览效果
2020/07/22 PHP
javascript sudoku 数独智力游戏生成代码
2010/03/27 Javascript
javascript实现的使用方向键控制光标在table单元格中切换
2010/11/17 Javascript
lyhucSelect基于Jquery的Select数据联动插件
2011/03/29 Javascript
javascript 基础篇1 什么是js 建立第一个js程序
2012/03/14 Javascript
jquery插件制作 图片走廊 gallery
2012/08/17 Javascript
jquery中交替点击事件toggle方法的使用示例
2013/12/08 Javascript
jQuery实现table隔行换色和鼠标经过变色的两种方法
2014/06/15 Javascript
jquery+php实现搜索框自动提示
2014/11/28 Javascript
jQuery的remove()方法使用详解
2015/08/11 Javascript
jQuery设置单选按钮radio选中/不可用的实例代码
2016/06/24 Javascript
使用bootstrap typeahead插件实现输入框自动补全之问题及解决办法
2016/07/07 Javascript
学习vue.js表单控件绑定操作
2016/12/05 Javascript
微信小程序 数组中的push与concat的区别
2017/01/05 Javascript
Javascript 实现计算器时间功能详解及实例(二)
2017/01/08 Javascript
JavaScript DOM节点操作实例小结(新建,删除HTML元素)
2017/01/19 Javascript
JS中的算法与数据结构之栈(Stack)实例详解
2019/08/20 Javascript
vue项目实现图片上传功能
2019/12/23 Javascript
jquery html添加元素/删除元素操作实例详解
2020/05/20 jQuery
vue-video-player实现实时视频播放方式(监控设备-rtmp流)
2020/08/10 Javascript
python用来获得图片exif信息的库实例分析
2015/03/16 Python
深入解答关于Python的11道基本面试题
2017/04/01 Python
Python字典操作详细介绍及字典内建方法分享
2018/01/04 Python
python 每天如何定时启动爬虫任务(实现方法分享)
2018/05/21 Python
Python箱型图绘制与特征值获取过程解析
2019/10/22 Python
详解python中各种文件打开模式
2020/01/19 Python
python GUI库图形界面开发之PyQt5拖放控件实例详解
2020/02/25 Python
html5 canvas 简单画板实现代码
2012/01/05 HTML / CSS
Nike香港官网:Nike HK
2019/03/23 全球购物
校园奶茶店创业计划书
2014/01/23 职场文书
教师党性分析材料
2014/02/04 职场文书
孝敬父母的活动方案
2014/08/28 职场文书
泰山导游词
2015/02/02 职场文书
恶魔之树最顶端的三颗果实 震震果实上榜,第一可以制造岩浆
2022/03/18 日漫