Python UTF-16 WAVY DASH编码问题/问题

时间:2010-02-15 21:48:31

标签: python unicode encoding utf-8 utf-16

我今天做了一些工作,遇到了“看起来很有趣”的问题。我一直在将一些字符串数据解释为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'

如果有人能告诉我这里到底发生了什么,我们将非常感激。

4 个答案:

答案 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)

你在这里被两件事搞糊涂了(也让我失望):

  1. utf-16和utf-32编码使用BOM,除非您通过utf-16-be等指定要使用的字节顺序。这是最后一行的\ xff \ xfe。
  2. '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解码。