编码方式和转码
来源:互联网 发布:mac创建新文件夹 编辑:程序博客网 时间:2024/06/05 09:36
以下内容是根据网上资料和个人理解整理出来的知识概要,如有错误,欢迎拍砖。
常用编码方式
常见的有四种:UTF-8、GB2312、GBK、GB18030。
先撇开UTF-8不谈,GB2312、GBK、GB18030这三种编码可以说都是为了汉字诞生的,三者的区别,可以简单理解为字符集大小的差异:GB2312 < GBK < GB18030。在这个不断扩充的过程中,少数民族语言、韩文、日文等各种字符也都被收录进来,发展到GB18030这一代,已经把世界大多民族的文字符号都囊括在内了。虽然GB18030的字符集可谓是最全面的,但是Windows系统下中文(中国)区域对应的默认代码页还是GBK。
那么,UTF-8又是怎么回事呢?要想理解她,必须先了解Unicode是什么东东。
大一统的Unicode
Unicode是为了世界和平和统一而诞生的。高大上吧,其实原理很简单:她把世界上所有的字符都列了出来,然后给每个字符分配了一个唯一编号,不管是什么平台也不管是什么语言,这个编号都不会发生改变。这种编码方式对应的通用字符集叫做UCS(Universal Character Set,UCS)-2。USC-2后面有个数字2是因为,目前的Unicode使用16位编码空间,即每个字符对应两个字节。
说到这里,终于可以揭开UTF-8的真面目了。她的全称是:Unicode Transformation Format-8bit。简单来说,UTF-8就是Unicode的一种实现方式或者说表现形式,主要是为了降低传输成本。她是一种可变长度字符编码方式,通常一个英文字符占用一个字节,一个汉字占用三个字节。对于绝大多数汉字而言,使用GB2312/GBK/GB18030是可以用两个字节表示的,因此对于汉字来说,使用UTF-8编码的弊端是会占用更多空间,但是由于UTF-8是基于Unicode的,她的优点在于:世界通用。
关于转码
铺垫了那么多,本文的重点终于出现了,那就是不同编码方式如何转换?其实很简单,那就是通过Unicode码做桥梁,实现GB2312/GBK/GB18030和UTF-8的相互转换。
可是如果这么简单,为何中文转码总会出现各种各样的问题呢?从这里开始水就深了,非要一句话总结的话,只能说汉字博大精深啊。下面列几个数字大家感受下。
在Unicode 5.0的99089个字符中,有71226个字符与汉字有关。它们的分布如下:
更多相关资料请戳:
字符集和字符编码(Charset & Encoding)
Unicode、GB2312、GBK和GB18030中的汉字
GB18030编码研究以及GBK、GB18030与Unicode的映射
case分享
下面说一下我遇到的转码问题。
一句话说重点:UTF-8转GBK时,映射到Unicode码中PUA(Private Use Area,用户造字区)码位的GBK码,用php中的mb_convert_encoding函数不能正确转码。
这句话看起来比较绕,简单点说是这样子的:
UTF-8转GBK需要先将UTF-8转Unicode,这一步是没有问题的。然后从Unicode转GBK,绝大部分汉字也都是没问题的。但是,,,有那么一些汉字(查资料得知是80个),GBK的收录时间早于Unicode,所以这些汉字的GBK码对应的Unicode码最开始是用Unicode自定义区的码位来映射的。大概是因为mb_convert_encoding函数只能支持映射到Unicode非PUA码位的字符转码,所以在给这些汉字转码时出现了错误。(这是推论出来的,未经验证)
解决这个问题有两个办法:
1、升级php版本到5.4+,因为mb_convert_encoding函数从5.4起支持GB18030字符集,这80个字符中有66个在GB18030中映射到了Unicode的非PUA码位。注意,对于其余14个字符,此办法仍旧不能正确转码。
2、针对这80个特殊字符,建立一张从Unicode码到GBK码的映射表。以下为测试通过的代码:
<?php/** * 转码工具类 */class ds_TranscodingModel { /** * 特殊字符从unicode码到gbk码的映射 */ private $transDict = array( 'e815' => 'fe50', 'e816' => 'fe51', 'e817' => 'fe52', 'e818' => 'fe53', 'e819' => 'fe54', 'e81a' => 'fe55', 'e81b' => 'fe56', 'e81c' => 'fe57', 'e81d' => 'fe58', 'e81e' => 'fe59', 'e81f' => 'fe5a', 'e820' => 'fe5b', 'e821' => 'fe5c', 'e822' => 'fe5d', 'e823' => 'fe5e', 'e824' => 'fe5f', 'e825' => 'fe60', 'e826' => 'fe61', 'e827' => 'fe62', 'e828' => 'fe63', 'e829' => 'fe64', 'e82a' => 'fe65', 'e82b' => 'fe66', 'e82c' => 'fe67', 'e82d' => 'fe68', 'e82e' => 'fe69', 'e82f' => 'fe6a', 'e830' => 'fe6b', 'e831' => 'fe6c', 'e832' => 'fe6d', 'e833' => 'fe6e', 'e834' => 'fe6f', 'e835' => 'fe70', 'e836' => 'fe71', 'e837' => 'fe72', 'e838' => 'fe73', 'e839' => 'fe74', 'e83a' => 'fe75', 'e83b' => 'fe76', 'e83c' => 'fe77', 'e83d' => 'fe78', 'e83e' => 'fe79', 'e83f' => 'fe7a', 'e840' => 'fe7b', 'e841' => 'fe7c', 'e842' => 'fe7d', 'e843' => 'fe7e', 'e844' => 'fe80', 'e845' => 'fe81', 'e846' => 'fe82', 'e847' => 'fe83', 'e848' => 'fe84', 'e849' => 'fe85', 'e84a' => 'fe86', 'e84b' => 'fe87', 'e84c' => 'fe88', 'e84d' => 'fe89', 'e84e' => 'fe8a', 'e84f' => 'fe8b', 'e850' => 'fe8c', 'e851' => 'fe8d', 'e852' => 'fe8e', 'e853' => 'fe8f', 'e854' => 'fe90', 'e855' => 'fe91', 'e856' => 'fe92', 'e857' => 'fe93', 'e858' => 'fe94', 'e859' => 'fe95', 'e85a' => 'fe96', 'e85b' => 'fe97', 'e85c' => 'fe98', 'e85d' => 'fe99', 'e85e' => 'fe9a', 'e85f' => 'fe9b', 'e860' => 'fe9c', 'e861' => 'fe9d', 'e862' => 'fe9e', 'e863' => 'fe9f', 'e864' => 'fea0', ); /** * 汉字转Unicode编码 * @param string $str 原始汉字的字符串 * @param string $encoding 原始汉字的编码 * @param boot $ishex 是否为十六进制表示(支持十六进制和十进制) * @param string $prefix 编码后的前缀 * @param string $postfix 编码后的后缀 */ function unicode_encode($str, $encoding = 'UTF-8', $ishex = false, $prefix = '&#', $postfix = ';') { $str = mb_convert_encoding($str, 'UCS-2', $encoding); $arrstr = str_split($str, 2); $unistr = ''; for($i = 0, $len = count($arrstr); $i < $len; $i ++) { $dec = $ishex ? bin2hex($arrstr[$i]) : hexdec(bin2hex($arrstr[$i])); $unistr .= $prefix . $dec . $postfix; } return $unistr; } /** * Unicode编码转汉字 * @param string $str Unicode编码的字符串 * @param string $decoding 原始汉字的编码 * @param boot $ishex 是否为十六进制表示(支持十六进制和十进制) * @param string $prefix 编码后的前缀 * @param string $postfix 编码后的后缀 */ function unicode_decode($unistr, $encoding = 'UTF-8', $ishex = false, $prefix = '&#', $postfix = ';') { $arruni = explode($prefix, $unistr); $unistr = ''; for($i = 1, $len = count($arruni); $i < $len; $i ++) { if (strlen($postfix) > 0) { $arruni[$i] = substr($arruni[$i], 0, strlen($arruni[$i]) - strlen($postfix)); } $temp = $ishex ? hexdec($arruni[$i]) : intval($arruni[$i]); $unicode = ($temp < 256) ? chr(0) . chr($temp) : chr($temp / 256) . chr($temp % 256); $tempHex = bin2hex($unicode); if(array_key_exists($tempHex, $this->transDict)) { $unistr .= pack("H*",$this->transDict[$tempHex]); } else { $unistr .= mb_convert_encoding($unicode, $encoding, 'UCS-2'); } } return $unistr; } /** * utf8编码转gbk编码 * @param string $str * @return string */ function utf8_to_gbk($str) { $gbkStr = mb_convert_encoding($str, 'GBK', 'UTF-8'); $utf8_str = mb_convert_encoding($gbkStr, 'UTF-8', 'GBK'); if($utf8_str == $str) { return $gbkStr; } $unistr = self::unicode_encode($str, 'UTF-8'); $str = self::unicode_decode($unistr, 'GBK'); return $str; }?>
- 编码方式和转码
- 字符集和编码方式
- 字符集和编码方式
- 字符集和编码方式
- 编码方式和乱码
- Virsual Studio 字符编码和编码方式
- 编码方式和字符集理解
- 哈夫曼树构造和编码方式
- get和post编码方式
- 常见字符集和编码方式
- 与编码方式有关的一些变量定义方式和强转方式
- QR码长度问题以及生成原理和编码方式
- [转]form表单提交数据编码方式和tomcat接受数据解码方式的思考
- vc6 和vs2008编码方式问题
- Mysql查看和修改编码方式
- 关于Unicode和其编码方式
- ANSI和UTF-8编码方式
- 查看和修改mysql编码方式
- ios图片处理
- 创建一个新闻信息的表需要的字段
- jdbc连接powerDesigner
- HTML5 教程
- Eclipse中将web项目自动发布到Tomcatwebapps下
- 编码方式和转码
- Java实验6 文件
- 一次被JOB整的很惨的经历
- 我的处女博
- FTP协议进行连接的两种方式
- backtrack5实现局域网DNS欺骗
- 文件的默认权限:umask
- opencv中文件路径的显示
- Cocos2d-x-3.0环境搭建