请注意——您向我们展示的“原始 utf-8 字符串”与此完全不同。
首先最重要的是,虽然它应该在最后:你的字符串的最终解码揭示了一个有效的中文短语 - 它在谷歌翻译中溢出了一个明显有效的翻译:“1 Hero build”:
第二件事:停止您现在正在做的任何事情,并阅读“Joel on Software”中关于 Unicode 的经典帖子。真的 - 它会让你变得更好 - 不要让标题让你觉得自己被嘲笑 - 阅读它。
第三 - 现在,让我们来看看你的数据有什么问题 - 你有一个 Python Unicode 对象,而不是“原始 utf-8 字符串”。当您将该特定字符串正确编码为 ut-8 时,您会得到一个字符串(字节)对象,该对象按字面意思读取 '1\xe6\x9c\x8d-\xe8\x8b\xb1\xe9\x9b\x84\xe9\x9b\x86\xe7\xbb\x93'
- 如果您将其放入s
变量中,并在索引 1 处获取字符,您会发现,您有一个斜杠( \
) 字符-也就是说,您在此处向我们展示的斜杠没有被用作转义序列的一部分,以将字节 "0xe6, 0x9c" 等编码为字符-它们确实存在。它repr
是'1\\xe6\\x9c\\x8d-\\xe8\\x8b\\xb1\\xe9\\x9b\\x84\\xe9\\x9b\\x86\\xe7\\xbb\\x93'
但是,它们应该只是 - 转义序列的一部分 - 所以你要做的就是将你的(字节)字符串解码s
回 unicode,但使用特殊的“unicode_escape”编解码器 - 这会给你一个 unicode 对象其中文字斜线实际上是它们前面的十六进制字节代码的转义字符:
>>> print s, repr(s)
1\xe6\x9c\x8d-\xe8\x8b\xb1\xe9\x9b\x84\xe9\x9b\x86\xe7\xbb\x93 '1\\xe6\\x9c\\x8d-\\xe8\\x8b\\xb1\\xe9\\x9b\\x84\\xe9\\x9b\\x86\\xe7\\xbb\\x93'
>>> s1 = s.decode("unicode_escape")
>>> print repr(s1)
u'1\xe6\x9c\x8d-\xe8\x8b\xb1\xe9\x9b\x84\xe9\x9b\x86\xe7\xbb\x93'
那个 unicode 对象作为 unicode 没有意义,但它的原始字节内容是 utf-8 中的实际最终字符串:
>>> print s1
1æ-è±ééç»
“latin-1”转换,主要是由于巧合,而不是因为“它就是这样”将 unicode 对象中的字节原样转换为普通(字节)字符串。这不是“unicode 的东西”——这是由于 Python unicode 对象的内部表示的值 0-255 与 latin-1 编码相匹配的巧合——因此“latin-1”中的编码提供了“透明“编码。标准中的任何内容都不会要求这样做。这个字符串,当被视为 UTF-8 时(注意,我在 utf-8 控制台中使用 Python 交互式解释器 - 您在使用 latin-1 或其他编码的 Python 提示符中看到的内容可能会有所不同)揭示了最肯定的是在这种情况下预期的字符串:
>>> s2 = s1.encode("latin-1")
>>> print repr(s2)
'1\xe6\x9c\x8d-\xe8\x8b\xb1\xe9\x9b\x84\xe9\x9b\x86\xe7\xbb\x93'
>>> print s2
1服-英雄集结