我今天做了一些工作,遇到了“看起来很有趣”的问题。我一直在将一些字符串数据解释为utf-8,并检查编码形式。数据来自ldap(特别是Active Directory),通过python-ldap。没有惊喜。
所以我偶然发现了字节序列'\ xe3 \ x80 \ xb0',当解码为utf-8时,它是unicode码点3030(wavy dash)。我需要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'
如果有人能告诉我这里到底发生了什么,我们将非常感激。
答案 0 :(得分:2)
这似乎是正确的行为。以UTF-16编码时的字符u'\ u3030'与UTF-8中的'00'编码相同。它看起来很奇怪,但它是正确的。
您可以看到'\ xff \ xfe'只是Byte Order Mark。
你确定你想要一个波浪般的短划线,而不是其他角色吗?如果您希望使用不同的角色,那么可能是因为在进入您的申请之前它已经被错误编码。
答案 1 :(得分: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 :(得分:1)
你在这里被两件事搞糊涂了(也让我失望):
'00'是两个字符digit zero。它不是空字符。无论如何,这打印方式不同:
>>> '\0\0'
'\x00\x00'
答案 3 :(得分:0)
上面的示例代码中存在一个基本错误。请记住,您编码 Unicode到编码的字符串,并且解码从编码的字符串返回到Unicode。所以,你这样做:
'\xe3\x80\xb0'.decode('utf-8').encode('utf-16-le').decode('utf-8')
转换为以下步骤:
'\xe3\x80\xb0' # (some string)
.decode('utf-8') # decode above text as UTF-8 encoded text, giving u'\u3030'
.encode('utf-16-le') # encode u'\u3030' as UTF-16-LE, i.e. '00'
.decode('utf-8') # OOPS! decode using the wrong encoding here!
在UTF-16LE中确实将'u'\ u3030'编码为'00'(ascii为零两次),但你不知何故认为这是一个空字节('\ 0')或其他东西。
请记住,如果使用one编码并使用其他编码进行解码,则无法访问相同的字符:
>>> import unicodedata as ud
>>> c= unichr(193)
>>> ud.name(c)
'LATIN CAPITAL LETTER A WITH ACUTE'
>>> ud.name(c.encode("cp1252").decode("cp1253"))
'GREEK CAPITAL LETTER ALPHA'
在此代码中,我编码为Windows-1252并从Windows-1253解码。在您的代码中,您编码为UTF-16LE并从UTF-8解码。