我有一个从Java传输到python的UTF8字符串。
最终结果是
'\xe0\xb8\x9a\xe0\xb8\x99'
因此,例如
a = '\xe0\xb8\x9a\xe0\xb8\x99'
a.decode('utf-8')
给我结果
u'\u0e1a\u0e19'
然而,我很好奇的是因为字节以UTF-8的形式传输,为什么会是
'\xe0\xb8\x9a\xe0\xb8\x99'
而不是u'\u0e1a\u0e19'
。
如果我要编码(u'\u0e1a\u0e19')
,我会回来'\xe0\xb8\x9a\xe0\xb8\x99'.
那么这两者之间的固有差异是什么以及我如何真正理解何时使用解码和编码。
答案 0 :(得分:2)
UTF8字符串不足以描述语句'\xe0\xb8\x9a\xe0\xb8\x99'
;它应该被称为unicode字符串的UTF8编码。
Python 2的unicode
类型和Python 3的str
类型表示一串unicode代码点,因此语句u'\u0e1a\u0e19'
是两个代码点U+0E1A U+0E19
的python表示形式在人类术语中,它将呈现为บน
。
至于解释整个encode
和decode
来电,我们将使用您的示例。您从Java获得的是一个原始字节流,因此为了使其作为人类文本有用,您需要decode
'\xe0\xb8\x9a\xe0\xb8\x99'
作为utf-8
编码输入才能获得该字节到他们代表的unicode代码点(u'\u0e1a\u0e19'
)。在该字符串的unicode代码上调用encode
指向一个字节列表(在Python 2中它将是str
类型,而Python 3实际上是bytes
类型)将返回到'\xe0\xb8\x9a\xe0\xb8\x99'
的一系列字节。
当然,您可以将这些unicode代码点编码为其他编码,例如UTF16编码,在小端平台上它将产生字节'\xff\xfe\x1a\x0e\x19\x0e'
,或者使用将这些代码点编码为非unicode编码。由于这看起来像泰语,我们可以使用iso8859-11
编码,它将被编码为字节'\xba\xb9'
- 但这不是跨平台的,因为它只会在为此配置的系统上显示为泰语特殊编码。这是发明Unicode的原因之一,因为这些字节'\xba\xb9'
可以使用iso8859-1
编码进行解码,º¹
或iso8859-11
为บน
}。
简而言之,'\xe0\xb8\x9a\xe0\xb8\x99'
是Python语法中u'\u0e1a\u0e19'
的unicode代码点的UTF8编码。原始字节(通过线路,从文件读取)通常不是unicode代码点的形式,它们必须被解码为unicode代码点。 Unicode代码点不是编码,当通过线路(或写入文件)发送时,必须将其编码为unicode代码点的某种字节表示形式,在许多情况下,它是utf-8,因为它具有最大的可移植性。
答案 1 :(得分:2)
'\ xe0 \ xb8 \ x9a \ xe0 \ xb8 \ x99'只是一系列字节。 您选择将其解释为UTF-8,当您这样做时,您可以将其解码为一系列unicode字符,U + e1a和U + e19。
序列U + e1a,U + e19可以表示为u'\ u0e1a \ u0e19',但在某种意义上,该表示与'\ xe0 \ xb8 \ x9a \ xe0 \ xb8 \ x99'一样任意。这是“自然的”,这就是为什么Python以这种方式打印它们,但它是无效的,这就是为什么有各种其他编码方案,包括UTF-8
事实上,对我说“'\ xe0 \ xb8 \ x9a \ xe0 \ xb8 \ x99'是一系列字节有点误导。”它是一系列字节的默认表示,二百二十四,接着是一百八十四,依此类推。
Python有一系列字节的概念,它有一系列unicode字符的单独概念。 encode
和decode
代表了这两种观念之间的映射方式。
这有帮助吗?