【问题标题】:Unicode characters Ú and É are displayed incorrectly as Ú and ÉUnicode 字符 Ú 和 É 错误地显示为 Ú 和 É
【发布时间】:2015-12-23 11:12:20
【问题描述】:

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

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

>>> b'\x4A\x45\x53\xC3\x9A\x53'.decode('utf-8')
'JESÚS'

c39a\u00da 的正确 UTF-8 编码,根据 http://www.fileformat.info/info/unicode/char/00da/index.htm

那么,为什么有些软件渲染不正确呢?

【问题讨论】:

  • 因为解码不正确,见en.wikipedia.org/wiki/Mojibake
  • “为什么有些软件渲染不正确?” 太宽泛了。是 Python 3 软件吗?是Windows系统上的文本文件吗?

标签: python unicode utf-8 mojibake


【解决方案1】:

这是使用 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/9a/index.htm http://www.fileformat.info/info/unicode/char/89/index.htm

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

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

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

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

Windows-1252ISO 8859-1 的超集,可打印字符为 0x80-0x9f。

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

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

【讨论】:

  • 不是Latin-1,是CP1252。
  • @MartijnPieters 实际上,它是 Windows-1252。我更新了答案。谢谢!
【解决方案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 映射到š89: p>

>>> u'Ú and É'.encode('utf8').decode('cp1252')
u'\xc3\u0161 and \xc3\u2030'
>>> print u'Ú and É'.encode('utf8').decode('cp1252')
Ú and É

请注意,该样本中的 ASCII 字符(空格和单词 and)不受影响,因为 UTF-8 和 CP1252 都使用这些字符的确切字节;前 127 个字节都使用 ASCII。

【讨论】:

    【解决方案3】:

    自动检测文本编码是不可靠的。尽管对于我们人类来说,在许多情况下,经过一些练习后很明显,无论您想出什么程序,某些文本输入都可能会失败。例如,讨论字符编码损坏的文本,如本页(!)

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

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

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

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

    对于所有其他程序,由它们决定 - 您是否有任何示例想要实现?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 1970-01-01
      • 2021-05-02
      • 2013-04-11
      • 1970-01-01
      • 2013-12-30
      相关资源
      最近更新 更多