[转]PHP程序中的汉字编码探讨
需求:内容按照【UNICODE使用Big Endian 字节顺序】编码后,需要转成16进制HEX字符串
UNICODE使用Big Endian 字节顺序 - UCS-2BE
转码如下:
$content=strtoupper(bin2hex(iconv('utf-8','UCS-2BE',$content)));
最近在做一个百度词典的采集,http://dict.baidu.com,发现了一个可以值得探讨的一个问题,汉字的编码问题。首先,我们输入一个汉字词语进行搜索,比如,我们,URL上的地址变成http://dict.baidu.com/s?wd=%CE%D2%C3%C7,前面的http://dict.baidu.com/s?wd=就不用管了,都知道是什么意思,我们关注一下后面“%CE%D2%C3%C7”这几个东西。显然是词语“我们”这个的汉字编码。我们知道PHP有个函数urlencode,可以把汉字转换为类似那样行事的。,得到结果为:%E6%88%91%E4%BB%AC。
显然,不是%CE%D2%C3%C7这种格式的。是不是进制的问题呢?还是汉字编码的问题(UTF-8或者GB2312)。我们做一下实验。
我们先进行转码:
1 2 3 4 5 6 7 |
<?php
$str = '我们'; //iconv('utf-8','cp936',$str); //echo urlencode($str); iconv('cp936','utf-8',$str); echo urlencode($str); ?> |
发现输出结果都为:%E6%88%91%E4%BB%AC,因为我测试的页面为utf-8的页面。所以结果一样。当页面为GBK或者GB2312的时候结果为:%CE%D2%C3%C7,这样,就和百度上的那个编码一致了。现在我们主要讨论页面编码为UTF8的时候,怎么得到正确的编码。
汉字的编码究竟是如何做的。我们知道,国内大部分都是GBK编码的,我们知道,GBK编码中一个汉字由二个字符组成,获取汉字字符串的方法如下:
1 2 3 4 5 6 7 8 9 10 11 |
<?php
$string = "我们"; $length = strlen($string); for($i=0;$i<$length;$i++){ if(ord($string[$i])>127){ $result[] = ord($string[$i]).' '.ord($string[++$i]); } } var_dump($result); ?> |
由于一个汉字为两个字符组成,通过ord()函数获取字符的ASCII值如果大于127时,就可以确定当前字符为一个汉字的前半部分,还需要获取汉字的后半部分。当然,这种判断的方法要结合具体的开发环境,如果存在ASCII值大于127的单个字符,这种方法判断显然就不正确。得到结果为一个数组:
GBK编码的页面结果:
1 2 3 4 5 6 |
array(2) {
[0]=> string(7) "206 210" [1]=> string(7) "195 199" } |
UTF-8的页面结果:
1 2 3 4 5 6 7 8 |
array(3) {
[0]=> string(7) "230 136" [1]=> string(7) "145 228" [2]=> string(7) "187 172" } |
GB2312的页面结果:
1 2 3 4 5 6 |
array(2) {
[0]=> string(7) "206 210" [1]=> string(7) "195 199" } |
从以上结果可以看出,如果页面编码为国标编码的时候,一个汉字是由两个字节组成。而页面编码为UTF8的时候,汉字是由三个字节组成的。但是进制都是十进制的,而我们需要的是十六进制的。那么怎么把十进制的汉字编码转换为十六进制呢?
可以采用以下办法,php由几个内建函数可以直接转换进制,decbin(),十进制转换为二进制;dechex(),十进制转换为十六进制;decoct(), 十进制转换为八进制。
1 2 3 4 5 6 7 |
<?php
foreach($result as $v){ $dec = explode(" ",$v); $strings[] = dechex($dec[0])." ".dechex($dec[1]); } var_dump($strings); ?> |
UTF8下得到结果为:
1 2 3 4 5 6 7 8 |
array(3) {
[0]=> string(5) "e6 88" [1]=> string(5) "91 e4" [2]=> string(5) "bb ac" } |
看到没,成了十六进制了,同理,转换二进制或者八进制只需将dechex函数换成decbin或者decoct就可以了。
现在我们明白汉字编码和转换进制问题了。
接着我们的问题继续,在UTF8页面上实现转换UTF8汉字为十六进制的GBK汉字编码。
首先学习两个函数:strtoupper() 函数把字符串转换为大写;base_convert() 函数在任意进制之间转换数字;iconv() 函数,实现各种字符集间的转换。mb_detect_encoding() 函数,判断汉字编码。
以上是分步进行转换,先得到汉字编码的十进制编码,然后我们用进制转换函数得到我们想要的汉字编码。下面我们依然这样做。
因为我们的页面是UTF8的页面。所以,我们先得到汉字的十进制编码,当然是UTF8下的编码,然后转成UTF8的十六进制编码。然后使用iconv函数进行字符集转换就了。废话少说,看代码:
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php
function convertStr($str) { $strlength = strlen($str); $cstr = ''; for($i = 0; $i < $strlength; $i++) { $cstr .= "%".strtoupper(base_convert(ord($str{$i}), 10, 16)); } return $cstr; } $contents = ($contentscharset = mb_detect_encoding($s, "ASCII, UTF-8, GB2312, GBK")) == "GB2312" ? $s : iconv($contentscharset, "CP936", $s); $w = convertStr($contents); ?> |
现在$w就是我们想要的十进制GBK下的汉字编码了了。
convertStr()函数,把汉字以16进制输出。首先判断汉字编码如果是UTF8则由UTF8转换成GBK的。然后执行convertStr()函数,完成进制转换。得到结果为:%CE%D2%C3%C7,这样,我们就得到了这个UTF8下的GBK汉字编码了。
<?php
//测试时文件的编码方式要是UTF8
$str='中文a字1符';
echo strlen($str).'<br>';//14
echo mb_strlen($str,'utf8').'<br>';//6
echo mb_strlen($str,'gbk').'<br>';//8
echo mb_strlen($str,'gb2312').'<br>';//10
/*
结果分析:在strlen计算时,对待一个UTF8的中文字符是3个长度,所以“中文a字1符”长度是3*4+2=14
在mb_strlen计算时,选定内码为UTF8,则会将一个中文字符当作长度1来计算,所以“中文a字1符”长度是6
*/
//利用这两个函数则可以联合计算出一个中英文混排的串的占位是多少(一个中文字符的占位是2,英文字符是1)
echo (strlen($str) + mb_strlen($str,'UTF8')) / 2;
//例如 “中文a字1符” 的strlen($str)值是14,mb_strlen($str)值是6,则可以计算出“中文a字1符”的占位是10.
echo mb_internal_encoding();
PHP内置的字符串长度函数strlen无法正确处理中文字符串,它得 到的只是字符串所占的字节数。对于GB2312的中文编码,strlen得到的值是汉字个数的2倍,而对于UTF-8编码的中文,就是3倍的差异了(在 UTF-8编码下,一个汉字占3个字节)。
采用mb_strlen函数可以较好地解决这个问题。mb_strlen的用法和 strlen类似,只不过它有第二个可选参数用于指定字符编码。例如得到UTF-8的字符串$str长度,可以用 mb_strlen($str,'UTF-8')。如果省略第二个参数,则会使用PHP的内部编码。内部编码可以通过 mb_internal_encoding()函数得到。需要注意的是,mb_strlen并不是PHP核心函数,使用前需要确保在php.ini中加载 了php_mbstring.dll,即确保“extension=php_mbstring.dll”这一行存在并且没有被注释掉,否则会出现未定义函 数的问题。
实例: 中文,用16进制转换
$string = ",";$length = strlen($string); for($i=0;$i<$length;$i++){ $result[] = '0x' . strtolower(base_convert(ord($string{$i}), 10, 16));//ord($string[$i]); } echo 'chr(' . implode(') . chr(', $result) . ')';
$tags = str_replace(array(chr(0xa3).chr(0xac), chr(0xa1).chr(0x41), chr(0xef).chr(0xbc).chr(0x8c)), ',', censor($tags));
转载于:https://www.cnblogs.com/bandbandme/p/3154186.html
[转]PHP程序中的汉字编码探讨相关推荐
- JSP/Servlet中的汉字编码问题
JSP/Servlet中的汉字编码问题 问题的起源 每个国家(或区域)都规定了计算机信息交换用的字符编码集,如美国的扩展 ASCII码, 中国的 GB2312-80,日本的 JIS 等,作为该国家/区 ...
- graphql redux_如何在Redux应用程序中使用GraphQL
graphql redux by Howon Song 通过宋颂恩 如何在Redux应用程序中使用GraphQL (How to use GraphQL in your Redux app) Fetc ...
- 在ASP.NET Core应用程序中使用分布式缓存
本文要点 ASP.NET Core内置了分布式缓存接口. 分布式缓存的主要好处有性能.数据共享和稳定性. Couchbase服务器是一个内存优先的数据库,非常适合作为分布式缓存. NuGet程序包使得 ...
- 在DevExpress程序中使用GridView直接录入数据的时候,增加列表选择的功能
在我上篇随笔<在DevExpress程序中使用Winform分页控件直接录入数据并保存>中介绍了在GridView以及在其封装的分页控件上做数据的直接录入的处理,介绍情况下数据的保存和校验 ...
- db2 参数标识符使用无效_在Python应用程序中使用配置的最佳实践
大多数计算机应用程序都可以使用配置来指定行为,无论是通过命令行标志.环境变量还是配置文件.作为一名软件开发人员,处理配置时会遇到一些挑战,例如解析不合法的输入.验证它以及在程序的任意位置访问它.以Py ...
- 寻找下一款Prisma APP:深度学习在图像处理中的应用探讨
在9月23日到9月24日的MDCC 2016年中国移动者开发大会"人工智能与机器人"专场中,阿里云技术专家周昌进行了题为<寻找下一款Prisma APP:深度学习在图像处理中 ...
- vaadin_Vaadin应用程序中的EJB查找
vaadin 自从我实现上一个服务定位器以来已经有很长时间了. 考虑到Java EE CDI (上下文和依赖注入)的成熟度,我认为不再需要. 我的第一个实现是在基于Struts的Web应用程序中使用E ...
- Web应用程序中的Spring JDBC入门
在上一篇文章中,我已经向您展示了如何设置基本的Spring 3 MVC Web应用程序 . 重复使用该项目设置作为模板,我将向您展示如何增强它以与JDBC一起使用. 有了它,您可以存储和检索数据库中的 ...
- Vaadin应用程序中的EJB查找
自从我实现上一个服务定位器以来已经有很长时间了. 我认为不再需要考虑Java EE CDI (上下文和依赖注入)的成熟度. 我的第一个实现是在基于Struts的Web应用程序中使用EJB. 之后,我开 ...
最新文章
- java使用httpclient调用上传图片接口[示例]
- html股票数据代码,股票数据的网站抓取(4.2)代码优化
- 数据科学 IPython 笔记本 8.4 简单的折线图
- jquery读取json文件跨域_跨域方法的若干种方式
- Servlet获取全路径
- tiny4412 编译并烧写系统
- MySQL中的蠕虫复制
- macOS CLion 上搭建 GLFW + GLAD OpenGL开发环境
- 非洲Affrike单词
- python pygame 动画_pygame行走的小猫多帧动画演示程序
- selenium:表单frame切换和句柄窗口切换
- 数据结构--基本概念
- Codeforces Round #439 (Div. 2) C.The Intriguing Obsession(组合数、记忆化搜索)
- wps word文档生成目录的时候显示断裂会生成大纲怎么办_word目录制作技巧:快速生成文档总目录和章节下子目录...
- 服部周作《麦肯锡晋升法则》读书笔记 I
- html5待办事项模板,待办事项列表模板
- 如何看懂html和css,怎么能看懂css
- [小甲鱼] 零基础入门python第031讲课后测试题及答案:永久存储,腌制一缸美味的泡菜
- 让镜头数量之争终结!Holga iPhone外壳暴力集成10个镜头
- 放假期间网站被挂马的解决办法
热门文章
- mysql char和varchar_MySQL char与varchar的差异
- 1202年最新最详细最全的synchronized知识详解
- creator找不到编译器 qt_VS2017直接使用QT库创建程序
- Rumor CodeForces - 893C
- mac m1下编译spring框架
- 合并区间—leetcode56
- java redis服务_java链接redis服务器
- WinPcap pcap_next_ex抓包
- IsWow64Process 判断操作系统位数
- windows7不支持AllocateAndGetTcpExTableFromStack