Unicode 与 UTF-8, GBK
Friday, 24. November 2006, 03:29:34
我想这里有几个概念要澄清~ 这样才能有比较好的交流的基础,而不是说同一个名字,却各自指的不是同一个东西。我也只是班门弄斧,希望大家指正。
unicode是一个字符集,不是一种编码,她只是定义了一个字符空间,把字符集中的字符映射到了相应的整数上,并为每一个字符提供了唯一的名字,比如,'中' U+4E2D。但unicode并没有定义编码方式(codec),也就是从字符集到字节序列的映射方式。有专门为unicode定义的编码方式,比如utf-8,utf-16(be/le),他们定义了unicode字符到字节序列的映射,也就是编码。utf-16简单的用16bit两个字节来编码(encode)unicode,utf-8用1倒3个或者更多的字节编码(encode)一个unicode字符。这些codec同时也定义了如何从一个字节序列中decode出unicode字符序列的方式。所以,unicode是一个抽象的字符概念,并不是一个字节流,她到字节流的映射靠codec来完成。python中,用unicode对象来表示抽象的unicode字符,我觉得到这个程度就可以了,不必关心其中是不是靠整数来表示的。关键是string对象就是字节流,python的unicode对象不同于string对象,抽象的unicode对象到字节流的string对象之间需要靠codec来转换。(在py3k中可能要统一unicode和string对象,再
议)
而gbk也是一个字符集,但同时他也定义了gbk这种codec(一种mbcs的codec),它定义了一个gbk字符(英文或者中文)到字节序列(一个或者两个字节)的映射。因为unicode的集合比gbk大,使gbk的超集,所以,可以把gbk编码的字节流转换成unicode字符序列,也可以把一部分的unicode字符(gbk子集的部分)编码为gbk的字节序列。所以,gbk也可以作为unicode的一种codec来用。
比如:(我现在在windows下面,所以默认的编码就是gbk的)
>>> sgbkzhong = '中'#输入默认gbk编码的string对象
>>> sgbkzhong#这是个以gbk编码的两个字节的字节流
'\xd6\xd0'
>>> len(sgbkzhong)#所以她的长度是2
2
>>> uzhong=unicode(sgbkzhong,'gbk')#可以将这个字符序列decode成unicode对象
>>> uzhong#这个unicode是U+4E2D
u'\u4e2d'
>>> len(uzhong)#这个unicode字符序列的长度是1
1
>>> sutf8zhong=uzhong.encode('utf-8')
>>> sutf8zhong
'\xe4\xb8\xad'
>>> len(sutf8zhong)#编码成utf-8的字节流,长度是3
3
>>> sutf16bezhong=uzhong.encode('utf-16be')
>>> sutf16bezhong
'N-'
>>> len(sutf16bezhong)#编码成utf-16be的字节流,长度是2
2
>>> sutf16bezhong.encode('hex')#我们看一下'N-'对应的hex
'4e2d'
>>>
以上说明的是python中unicode和string(字节流)之间的关系。而socket接口只能传输字节流,她并不关心你的内容是什么,自然也不能传什么抽象的unicode对象,她只能传输将unicode编码过的字节流。所以,python的socket接口只能处理string对象,如果不是string对象,会被首先转换成string对象。
具体到你这个问题,
On Thu, 23 Nov 2006 13:34:45 +0800, limodou
<limodou@gmail.com> wrote:
> On 11/23/06, 隋刚 <blackjacksg@gmail.com> wrote:
>> 实在是头大了,我又尝试了一下,因为是跟vc写的客户端(使用了unicode编码)进
>> 行通讯,分析了一下里面的数据,发现在每一个客户端发过来的字符前面加入了
>> '00',而不管我怎么转换,发过去的都是8位的ASCII字符,看看有什么好的解决办
>> 法没有?
> 那它可能使用的是utf-16-be编码吧。如:
> >>> a.encode('utf-16-be')
> '\x00a'
我想limodou已经替你解决了,我的理解和他一样,你的vc的客户端使用的应该是utf-16be的编码,不知道你使用这种方法后的结果怎么样了。
至于你之前的代码,为什么直接send unicode对象,对方却接收到的是ascii字符串,原因是send()函数会把你的unicode对象用str()转换成string对象,使用的codec是你指定的'utf-8',因为都是英文字符,所以,utf-8编码的结果是和ascii一致的。
On Mon, 20 Nov 2006 17:58:49 +0800, 隋刚
<blackjacksg@gmail.com> wrote:
> 请问使用python的socket module发送unicode的信息怎么发送,我试着转换了一
> 下,发送到服务器端还是ascii的,可以看看我的源程序,谢谢。
> import socket
> import sys
> reload(sys)
> sys.setdefaultencoding('utf-8')
> host = "192.168.3.111"
> port = 8888
> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> s.connect((host, port));
> str = u'<?xml version=\"1.0\" ?><Request type=\"Distribute\"/>'
> s.send(str)
> date = s.recvfrom(4096)
> s.close()
> print repr(date)
顺便推荐一下这篇FAQ,对Unicode讲解得很通透,让我明白了很多原先很混乱的概念。
UTF-8 and Unicode FAQ for Unix/Linux
这儿有一个捎老一点的中文版





