如何在Python2中将utf-8字节数组解码为字符串?

时间:2016-08-02 17:55:46

标签: python arrays python-2.7 utf-8

我有一个表示utf-8编码字符串的字节数组。我想将这些字节解码回Pyton2中的字符串。我依靠Python2来完成整个程序,所以我无法切换到Python3。

array = [67, 97, 102, **-61, -87**, 32, 70, 108, 111, 114, 97] 

- > Caf é Flora

由于我想要的字符串中的每个字符不一定由数组中的1个字节表示,我不能使用如下解决方案:

"".join(map(chr, array))

我尝试创建一个可以逐步执行数组的函数,每当遇到不在0-127(ASCII)范围内的数字时,创建一个新的16位int,将当前位移到8以上,然后使用按位OR添加以下字节。最后,它将使用unichr()对其进行解码。

result = []


for i in range(len(byte_array)):
    x = byte_array[i]
    if x < 0:
        b16 = x & 0xFFFF # 16 bit
        b16 = b16 << 8
        b16 = b16 | byte_array[i+1]
        result.append(unichr(m16))
    else:
        result.append(chr(x))

return "".join(result)

然而,这是不成功的。

以下文章很好地解释了这个问题,并包含了nodeJS解决方案:

http://ixti.net/development/node.js/2011/10/26/get-utf-8-string-from-array-of-bytes-in-node-js.html

3 个答案:

答案 0 :(得分:2)

使用很少使用的array module将您的输入转换为字节字符串,然后使用UTF-8编解码器将其decode转换为:

import array
decoded = array.array('b', your_input).tostring().decode('utf-8')

答案 1 :(得分:1)

你必须要记住,Python2中的“字符串”不是正确的文本,只是内存中的一个字节序列,当你“打印”它们时恰好会映射到字符 - 如果打算将字符映射到字节序列与终端中的字节序列匹配,您将看到格式正确的文本。

如果您的终端不是UTF-8,即使您在内存中获得了正确的字节标记,只需打印它就会显示错误的结果。这就是为什么在表达式结束时需要额外的“解码”步骤。

text = b''.join(chr(i if i > 0 else 256 + i) for i in array).decode('utf-8')

由于您的源将128到255之间的数字编码为负数,我们在调用“chr”之前使用内联“if”运算符重新规范化该值。

只是要清楚 - 你说“因为我想要的字符串中的每个字符都不一定由数组中的1个字节表示,” - 所以 - 如果你使用Python2.x字符串,需要注意的是, 终端无论如何。如果你想处理正确的tet,在将你的数字加到一个合适的(字节)字符串之后,就是使用“decode”方法 - 这是知道UTF-8多字节编码字符的部分并且还给你回来一个(文本)字符串对象(Python 2中的'unicode'对象) - 将每个字符视为一个实体。

答案 2 :(得分:1)

您可以将struct.pack用于此

>>> a =  [67, 97, 102, -61, -87, 32, 70, 108, 111, 114, 97]
>>> struct.pack("b"*len(a),*a)
'Caf\xc3\xa9 Flora'
>>> print struct.pack("b"*len(a),*a).decode('utf8')
Café Flora