`
ggsonic
  • 浏览: 259395 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多
1. Unicode和UTF-8
为了统一全世界各国语言文字和专业领域符号(例如数学符号、乐谱符号)的编码,ISO制定了ISO 10646标准,也称为UCS(Universal Character Set)。UCS编码的长度是31位,可以表示231个字符。如果两个字符编码的高位相同,只有低16位不同,则它们属于一个平面(Plane),所以一个平面由216个字符组成。目前常用的大部分字符都位于第一个平面(编码范围是U-00000000~U-0000FFFD),称为BMP(Basic Multilingual Plane)或Plane 0,为了向后兼容,其中编号为0~256的字符和Latin-1相同。UCS编码通常用U-xxxxxxxx这种形式表示,而BMP的编码通常用U+xxxx这种形式表示,其中x是十六进制数字。在ISO制定UCS的同时,另一个由厂商联合组织也在着手制定这样的编码,称为Unicode,后来两家联手制定统一的编码,但各自发布各自的标准文档,所以UCS编码和Unicode码是相同的。

有了字符编码,另一个问题就是这样的编码在计算机中怎么表示。现在已经不可能用一个字节表示一个字符了,最直接的想法就是用四个字节表示一个字符,这种表示方法称为UCS-4或UTF-32,UTF是Unicode Transformation Format的缩写。一方面这样比较浪费存储空间,由于常用字符都集中在BMP,高位的两个字节通常是0,如果只用ASCII码或Latin-1,高位的三个字节都是0。另一种比较节省存储空间的办法是用两个字节表示一个字符,称为UCS-2或UTF-16,这样只能表示BMP中的字符,但BMP中有一些扩展字符,可以用两个这样的扩展字符表示其它平面的字符,称为Surrogate Pair。无论是UTF-32还是UTF-16都有一个更严重的问题是和C语言不兼容,在C语言中0字节表示字符串结尾,库函数strlen、strcpy等等都依赖于这一点,如果字符串用UTF-32存储,其中有很多0字节并不表示字符串结尾,这就乱套了。

UNIX之父Ken Thompson提出的UTF-8编码很好地解决了这些问题,现在得到广泛应用。UTF-8具有以下性质:

编码为U+0000~U+007F的字符只占一个字节,就是0x00~0x7F,和ASCII码兼容。

编码大于U+007F的字符用2~6个字节表示,每个字节的最高位都是1,而ASCII码的最高位都是0,因此非ASCII码字符的表示中不会出现ASCII码字节(也就不会出现0字节)。

用于表示非ASCII码字符的多字节序列中,第一个字节的取值范围是0xC0~0xFD,根据它可以判断后面有多少个字节也属于当前字符的编码。后面每个字节的取值范围都是0x80~0xBF,见下面的详细说明。

UCS定义的所有231个字符都可以用UTF-8编码表示出来。

UTF-8编码最长6个字节,BMP字符的UTF-8编码最长三个字节。

0xFE和0xFF这两个字节在UTF-8编码中不会出现。

具体来说,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

第一个字节要么最高位是0(ASCII字节),要么最高两位都是1,最高位之后1的个数决定后面有多少个字节也属于当前字符编码,例如111110xx,最高位之后还有四个1,表示后面有四个字节也属于当前字符的编码。后面每个字节的最高两位都是10,可以和第一个字节区分开。这样的设计有利于误码同步,例如在网络传输过程中丢失了几个字节,很容易判断当前字符是不完整的,也很容易找到下一个字符从哪里开始,结果顶多丢掉一两个字符,而不会导致后面的编码解释全部混乱了。上面的格式中标为x的位就是UCS编码,最后一种6字节的格式中x位有31个,可以表示31位的UCS编码,UTF-8就像一列火车,第一个字节是车头,后面每个字节是车厢,其中承载的货物是UCS编码。UTF-8规定承载的UCS编码以大端表示,也就是说第一个字节中的x是UCS编码的高位,后面字节中的x是UCS编码的低位。

例如U+00A9(©字符)的二进制是10101001,编码成UTF-8是11000010 10101001(0xC2 0xA9),但不能编码成11100000 10000010 10101001,UTF-8规定每个字符只能用尽可能少的字节来编码

2. Python的ASCII, GB2312, Unicode , UTF-8
ASCII 是一种字符集,包括大小写的英文字母、数字、控制字符等,它用一个字节表示,范围是 0-127 Unicode分为UTF-8和UTF-16。
UTF-8变长度的,最多 6 个字节,小于 127 的字符用一个字节表示,与 ASCII 字符集的结果一样,ASCII 编码下的英语文本不需要修改就可以当作 UTF-8 编码进行处理。
Python 从 2.2 开始支持 Unicode ,函数 decode( char_set )可以实现 其它编码到 Unicode 的转换,函数 encode( char_set )实现 Unicode 到其它编码方式的转换。
比如
("你好").decode( "GB2312")

将得到
u'\u4f60\u597d',

即 "你"和“好"的 Unicode 码分别是 0x4f60 和 0x597d

再用
(u'\u4f60\u597d').encode("UTF-8")

将得到
'\xe4\xbd\xa0\xe5\xa5\xbd'

它是 “你好”的UTF-8编码结果。

python中使用 unicode的关键:unicode是一个类,函数unicode(str,"utf8")从utf8编码(当然也可以是别的编码)的字符串str生成 unicode类的对象,而函数unc.encode("utf8")将unicode类的对象unc转换为(编码为)utf8编码(当然也可以是别的编码)的字符串。于是,编写unicode相关程序,需要做的事情是 * 获取数据(字符串)时,用unicode(str, "utf8")生成unicode对象 * 在程序中仅使用unicode对象,对程序中出现的字符串常量都以u"字符串"的形式书写 * 输出时,可将unicode对象转换为任意编码输出,使用str.encode("some_encoding")

>>> unicode("你好", "utf8")
       u'\u4f60\u597d'

>>> x = _

>>> type(x)

>>> type("你好")

>>> x.encode("utf8")
       '\xe4\xbd\xa0\xe5\xa5\xbd'

>>> x.encode("gbk")
       '\xc4\xe3\xba\xc3'

>>> x.encode("gb2312")
       '\xc4\xe3\xba\xc3'

>>> print x
       你好

>>> print x.encode("utf8")
       你好

>>> print x.encode("gbk")
       ???

以上是测试结果(Ubuntu 6.06,locale为utf8),注意type(x)和type("你好")的区别。从编码上可以看出utf8编码与gbk不同。在utf8的 locale设置下,打印x按该环境变量编码(我猜我猜我猜猜猜),而打印x.encode("gbk")则是乱码。
分享到:
评论

相关推荐

    lua-utf8.zip

    Windows版:lua-utf8.dll(若是用在openresty中,openresty版本需使用32位版本,使用64位版本时会报错“lua-utf8.dll 不是有效的 Win32 应用程序”) 将lua-utf8库放在openresty安装目录下,使用时用require引入。

    批量转UTF8工具-批量转UTF8工具

    批量转UTF8工具批量转UTF8工具批量转UTF8工具批量转UTF8工具 批量转UTF8工具批量转UTF8工具批量转UTF8工具批量转UTF8工具

    CString转UTF8,UTF8转CString

    CString转UTF8,UTF8转CString。

    C++实现判断一个字符串是否为UTF8或GBK格式的方法

    本文实例讲述了C++实现判断一个字符串是否为UTF8或GBK格式的方法。分享给大家供大家参考,具体如下: 在处理外部数据的时候,很可能因为数据格式不一样而导致乱码,甚至导致某些程序挂掉。鉴于对多数系统来说,使用...

    全面了解mysql中utf8和utf8mb4的区别

    下面小编就为大家带来一篇全面了解mysql中utf8和utf8mb4的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    易语言UTF8解码

    易语言UTF8解码源码,UTF8解码

    md5_utf8.asp md5_utf8文件

    md5_utf8.asp md5_utf8文件

    UTF8BOM转换工具

    UTF8BOM转换工具

    JS GB2312转UTF8 支持中英文混合

    JS GB2312TOUTF8 UTF8TOGB2312 编码转换 /* * GB2312转UTF8 * 例: * var xx=new GB2312UTF8(); * var Utf8=xx.Gb2312ToUtf8("你aaa好aaaaa"); * var Gb2312=xx.Utf8ToGb2312(Utf8); * ...

    两个C++类:UTF8自动转换至Unicode,Unicode自动转换至UTF8

    两个C++类:UTF8自动转换至Unicode,Unicode自动转换至UTF8

    文本文件编码转换工具 gbk utf8 gb2312

    问题也是有的,在此环境下涉及到数据库运行的文件都必须是 utf8编码.这样一来就出现了不兼容,因为在国内大家都是以GBK gb2312编的码 包括 17PHP.com 网站里的学习源码文件(我用的是77例中的) 和很多插件 论坛代码......

    UTF8 to excel

    把xls文件名改为UTF8文件的文件名,再把UTF8文件拖到vbs文件上,就可以了

    utf8gb2312互转集成GB2312.txt

    例:utf8gb2312互转 /* * 例: * $xyy=new GB2312UTF8(); * $UTF8=$xyy->GB2312TOUTF8("i lover 你!"); * $GB2312=$xyy->UTF8TOGB2312($UTF8); * echo $UTF8." ".$GB2312; */

    lua utf8 unicode ansi 转换

    require "lc" print(lc.help());... u2w(utf8 to unicode) w2a(unicode to ansi) w2u(unicode to utf8) u2a(utf8 to ansi) a2u(ansi to utf8) bstr(bytes of str) help(show this) wunoman@qq.com 2012/03/06

    unicode和utf8编码相互转换C代码

    内容为utf8编码和unicode编码相互转换的C代码,关于utf8和unicode的用途另一篇博客有介绍,请参考。 压缩包 : ntf_code.rar 列表 ntf_code\uni_utf8.h ntf_code\utf8_u.c ntf_code\utf82u.c ntf_code\u2utf8.c ntf_...

    mysql数据库utf8转utf8mb4工具

    mysql数据库utf8转utf8mb4工具,将mysql数据库从utf8字符集转换为utf8mb4字符集,或将数据库从 utf8mb4字符集 转换为 utf8字符集。

    labview text to utf8

    labview默认的字符串中若存在汉字,发送给别人可能无法被别人正常解析,使用本模块可以将字符串转为utf8编码

    labview utf8toGBK

    使用labview时有时会遇到汉字乱码的情况,可能是因为汉字使用了UTF8编码,使用本模块可以成功解析

    文件编码转换(utf8与gbk相互转换)

    文件编码转换(utf8与gbk相互转换) 可以将utf8(gbk)的文件转换成gbk(utf8)格式

    JspSmartUpload_UTF8

    JspSmartUpload_UTF8版 增加了一个setCharset()方法 在upload()之前使用 例如: smartUpload = new SmartUpload(); smartUpload.initialize(config, request, response); smartUpload.setCharset("UTF-8"); ...

Global site tag (gtag.js) - Google Analytics