Python UTF-16 波浪线编码问题
今天我在工作时遇到了一些问题,感觉有些地方“看起来不对劲”。我一直在把一些字符串数据当作utf-8来处理,并检查它们的编码形式。这些数据是通过python-ldap从ldap(具体来说是Active Directory)获取的,没什么意外。
我几次遇到了字节序列'\xe3\x80\xb0',当把它解码为utf-8时,它对应的unicode字符是3030(波浪线)。我需要将字符串数据转换为utf-16,所以我自然使用了.encode('utf-16')来转换。不幸的是,似乎python对这个字符不太友好:
D:\> python
Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> u"\u3030"
u'\u3030'
>>> u"\u3030".encode("utf-8")
'\xe3\x80\xb0'
>>> u"\u3030".encode("utf-16-le")
'00'
>>> u"\u3030".encode("utf-16-be")
'00'
>>> '\xe3\x80\xb0'.decode('utf-8')
u'\u3030'
>>> '\xe3\x80\xb0'.decode('utf-8').encode('utf-16')
'\xff\xfe00'
>>> '\xe3\x80\xb0'.decode('utf-8').encode('utf-16-le').decode('utf-8')
u'00'
看起来IronPython也不喜欢这个:
D:\ipy
IronPython 2.6 Beta 2 (2.6.0.20) on .NET 2.0.50727.3053
Type "help", "copyright", "credits" or "license" for more information.
>>> u"\u3030"
u'\u3030'
>>> u"\u3030".encode('utf-8')
u'\xe3\x80\xb0'
>>> u"\u3030".encode('utf-16-le')
'00'
如果有人能告诉我,这到底是怎么回事,我会非常感激。
4 个回答
1
这里有两个让你困惑的地方(我当初也搞不清楚):
- utf-16和utf-32编码会使用一个叫做BOM的东西,除非你特别指定使用哪种字节顺序,比如utf-16-be之类的。这就是倒数第二行中的\xff\xfe。
'00'是两个字符,代表的是数字零。它不是一个空字符。即使是空字符,打印出来的效果也会不一样:
>>> '\0\0' '\x00\x00'
2
但是它解码得很好:
>>> u"\u3030".encode("utf-16-le")
'00'
>>> '00'.decode("utf-16-le")
u'\u3030'
这是因为那个字符的UTF-16编码恰好和'0'的ASCII码是一样的。你也可以用'\x30\x30'来表示它:
>>> '00' == '\x30\x30'
True
2
这看起来是正常的行为。字符 u'\u3030' 在 UTF-16 编码下和 '00' 在 UTF-8 编码下是一样的。虽然看起来有点奇怪,但这是正确的。
你看到的 '\xff\xfe' 只是一个 字节顺序标记。
你确定你想要的是波浪线吗,而不是其他字符?如果你希望得到的是不同的字符,可能是因为在进入你的应用程序之前,它已经被错误编码过了。