Unicode字符Ú和É显示不正确为Ã和É

时间:2015-12-23 11:12:21

标签: python unicode utf-8 mojibake

我有一个带有西班牙文字的UTF-8文件,并且某些带有重音符号的字词在某些软件中显示不正确。

我相信我的档案是正确的。例如,名称“JESÚS”编码为4A 45 53 C3 9A 53

>>> b'\x4A\x45\x53\xC3\x9A\x53'.decode('utf-8')
'JESÚS'
根据{{​​3}},

c39a\u00da的正确UTF-8编码。

那么,为什么某些软件会错误地呈现它呢?

3 个答案:

答案 0 :(得分:3)

这是使用Latin-1编码而不是UTF-8的结果。双字节UTF-8序列被错误地解码为两个字符。

>>> 'Ú'.encode('utf-8').decode('latin-1')
'Ã\x9a'
>>> 'É'.encode('utf-8').decode('latin-1')
'Ã\x89'

http://www.fileformat.info/info/unicode/char/00da/index.htm http://www.fileformat.info/info/unicode/char/9a/index.htm

这两个字符都是控制字符,因此它们可能会也可能不会显示在不同的软件中。

此外,重复不正确的编码 - 解码会进一步破坏文本:

>> 'Ú'.encode('utf-8').decode('latin-1').encode('utf-8').decode('latin-1')
'Ã\x83Â\x9a'

更新:如果您看到实际的š和‰(而不是不可见的控制字符),则错误的编码是Windows-1252。

http://www.fileformat.info/info/unicode/char/89/index.htmWindows-1252的超集,可打印字符为0x80-0x9f。

在Windows-1252中,代码点0x9a和0x89对应于字符šISO 8859-1 http://www.fileformat.info/info/unicode/char/0161/index.htm

>>> 'Ú'.encode('utf-8').decode('Windows-1252')
'Ú'
>>> 'É'.encode('utf-8').decode('Windows-1252')
'É'

答案 1 :(得分:2)

您正在使用不同编解码器解码数据的软件中打开文件。我猜他们正在Windows 1252 codepage打开它。这导致Mojibake乱码文字。

UTF-8 codec将Unicode代码点编码为变量字节数,具体取决于编码的字符。 Unicode标准的前127个字符(对应于ASCII标准)只需要一个字节,然后按照1920个Latin-1字符编码为两个字节等,一直到4个字节(UCS允许最多6个字节)每个代码点的字节数。)

您的文字包含2个Latin-1字符,因此每个字符需要2个字节:

>>> u'Ú and É'.encode('utf8')
'\xc3\x9a and \xc3\x89'

请注意空格和单词and如何编码为单个字节(Python将它们显示为我们的ASCII代码点,因为它比\x..转义序列更具可读性。

您的某些软件使用不同的编解码器解码该数据。 CP1252编解码器将每个字节解码为单个字符,因此C3被解码为Ã,而9A映射到š和{{ 1}}到89

请注意,该示例中的ASCII字符(空格和单词>>> u'Ú and É'.encode('utf8').decode('cp1252') u'\xc3\u0161 and \xc3\u2030' >>> print u'Ú and É'.encode('utf8').decode('cp1252') Ú and É )不受影响,因为UTF-8和CP1252都使用这些字符的确切字节;两者都使用ASCII作为前127个字节。

答案 2 :(得分:0)

自动检测文本编码是不可靠的。虽然对于我们人类而言,在许多情况下,在一些练习之后它显而易见,无论你想出什么样的程序,都可能因某些文本输入而失败。例如,讨论字符破碎编码的文本,如此页面(!)

因此,许多使用文本的程序根本不进行自动检测,而是依赖于指定编码的用户。

使用Unicode,有 BOM Byte Order Mark)可以为您提供帮助。在UTF-8中,如果您使用8位字符0xEF 0xBB 0xBF开始文本,它可以帮助某些程序确认整个文本的编码。

解释HTML文本的另一大类程序 - 然后您可以使用讨论选项的问题中显示的元标记:

<meta charset="utf-8"> vs <meta http-equiv="Content-Type">

对于所有其他程序,它们都是它们 - 您是否有任何想要工作的示例?