来自cStringI的Python“\x00”填充/utf-32字符串

2024-05-16 21:57:26 发布

您现在位置:Python中文网/ 问答频道 /正文

通过另一个系统的cStringIO,我通过:

u'content-length'.encode('utf-8')

在使用unicode( stringio_fd.read(),'utf-8')读回本文时,我得到:

u'c\x00\x00\x00o\x00\x00\x00n\x00\x00\x00t\x00\x00\x00e\x00\x00\x00n\x00\x00\x00t\x00\x00\x00-\x00\x00\x00l\x00\x00\x00e\x00\x00\x00n\x00\x00g\x00\x00\x00t\x00\x00h\x00\x00\x00'

在终端中打印上面的内容会给我正确的值,但当然,我不能做任何有用的事情:

print unicode("c\x00\x00\x00o\x00\x00\x00n\x00\x00\x00t\x00\x00\x00e\x00\x00\x00n\x00\x00\x00t\x00\x00\x00-\x00\x00\x00l\x00\x00\x00e\x00\x00\x00n\x00\x00\x00g\x00\x00\x00t\x00\x00\x00h\x00\x00\x00")

content-length

print unicode("c\x00\x00\x00o\x00\x00\x00n\x00\x00\x00t\x00\x00\x00e\x00\x00\x00n\x00\x00\x00t\x00\x00\x00-\x00\x00\x00l\x00\x00\x00e\x00\x00\x00n\x00\x00\x00g\x00\x00\x00t\x00\x00\x00h\x00\x00\x00") == u'content-length'

False

把这个字符串转换成等价于u'content-type'的字符串的最快、最便宜的方法是什么?我不能改变cStringIO


更新

虽然philhag的回答是正确的,但问题似乎是:

StringIO.StringIO(u'content-type').getvalue().encode('utf-8')

'content-type'

StringIO.StringIO(u'content-type').getvalue().encode('utf-8').decode('utf-8')

u'content-type'

cStringIO.StringIO(u'content-type').getvalue().encode('utf-8').decode('utf-8')

u'c\x00\x00\x00o\x00\x00\x00n\x00\x00\x00t\x00\x00\x00e\x00\x00\x00n\x00\x00\x00t\x00\x00\x00-\x00\x00\x00t\x00\x00\x00y\x00\x00\x00p\x00\x00\x00e\x00\x00\x00'

cStringIO.StringIO(u'content-type').getvalue().encode('utf-8').decode('utf-8').decode('utf-32')

u'content-type'


Tags: typeunicodecontentlengthutfencodedecodex00
2条回答

一路上有些东西把你的值编码成UTF-32。简单地解码它们:

>>> b = u"c\x00\x00\x00o\x00\x00\x00n\x00\x00\x00t\x00\x00\x00e\x00\x00\x00\
... n\x00\x00\x00t\x00\x00\x00-\x00\x00\x00l\x00\x00\x00e\x00\x00\x00\
... n\x00\x00\x00g\x00\x00\x00t\x00\x00\x00h\x00\x00\x00"
>>> b.decode('utf-32')
u'content-length'

根本原因是cStringIO.StringIO(unicode_object)产生了一个废话。

docs.python.org上的current 2.X docs

Unlike the StringIO module, this module is not able to accept Unicode strings that cannot be encoded as plain ASCII strings.

这是没有帮助和不正确的;见下文。win32安装程序为CPython 2.7.2和2.6.6提供的文档的chm版本如下:

Calling StringIO() with a Unicode string parameter populates the object with the buffer representation of the Unicode string instead of encoding the string.

这是对行为的正确描述(见下文)。这种行为并不聪明。我无法想象从web文档中删除这句话的好理由。

行为不端:

Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32
>>> import StringIO, cStringIO, sys
>>> StringIO.StringIO(u"fubar").getvalue()
u'fubar' <<=== unicode object
>>> cStringIO.StringIO(u"fubar").getvalue()
'f\x00u\x00b\x00a\x00r\x00' <<=== str object
cStringIO.StringIO(u"\u0405\u0406").getvalue()
'\x05\x04\x06\x04' <<=== "accepts"
>>> sys.maxunicode
65535 # your sender presumably emits 1114111 (wide unicode)
>>> sys.byteorder
'little'

所以一般来说,我们只需要知道/猜测发送者Python的endianness和unicode宽度,然后用UTF-(16|32)-(B|L)E解码混乱的内容。

在您的例子中,发送者是相当拜占庭式的;例如u'content-length'.encode('utf-8')str对象'content-length',它与您开始使用的对象具有显著的相似性。同时,foo.encode(utf8').decode('utf8')会产生foo或异常。

相关问题 更多 >