5

我正在将字节流解码为 un​​icode 字符,而不知道一百个左右的发送者中的每一个都使用的编码。

许多发件人在技术上并不精明,无法告诉我他们使用的是什么编码。这将取决于他们用来生成数据的工具链的偶然性。

目前,发件人都是基于英国/英语的,使用各种操作系统。

我可以要求所有发件人向我发送一个特定的字符串,该字符串将明确地展示每个发件人使用的编码吗?

我知道有些库使用启发式来猜测编码 - 我也将追究它,作为运行时后备,但首先我想尝试确定正在使用的编码,如果可以的话。

(不要认为它是相关的,但我正在使用 Python)

4

1 回答 1

4

这个问题的完整答案取决于许多因素,例如各种上游系统使用的编码范围,以及您的用户将如何遵守将魔术字符序列键入文本字段的说明,以及他们的熟练程度在晦涩的键盘组合中键入魔术字符序列。

有一些非常简单的字符序列,只有部分用户才能输入。只有使用西里尔文键盘和编码的用户会发现键入“Ильи́ч” (Ilyich) 很容易,因此您只需区分支持西里尔文的编码,如 UTF-8、UTF-16、iso8859_5 和 koi8_r。同样,您可以提出日语、中文和韩语字符序列,以区分日语、简体中文、繁体中文和韩语系统的用户。

但让我们专注于西欧计算机系统的用户,以及 ISO-8859-15、Mac_Roman、UTF-8、UTF-16LE 和 UTF-16BE 等常见编码。一个非常简单的测试是让用户输入欧元字符“€”,U+20AC,然后查看生成的字节序列:

  • byte ['\xa4'] 表示 iso-8859-15 编码
  • bytes ['\xe2', '\x82', '\xac'] 表示 utf-8 编码
  • bytes ['\x00', '\xac'] 表示 utf-16be 编码
  • bytes ['\xac', '\x00'] 表示 utf-16le 编码
  • byte ['\x80'] 表示 cp1252 ("Windows ANSI") 编码
  • byte ['\xdb'] 表示宏编码
  • iso-8859-1 根本无法代表欧元字符。iso-8859-15 是 iso-8859-1 的支持欧洲的继任者。
  • 美国用户可能不知道如何输入欧元字符。(好吧,这太刻薄了。3% 的人会知道。)

您应该检查这些字节序列中的每一个(解释为任何可能的编码)不是用户可能自己键入的字符序列。例如,iso-8859-15 Euro 符号的 '\xa4' 也可以是 '¤' 的 iso-8859-1 或 cp1252 或 UTF-16le 编码,'§' 的宏编码,或第一个字节数千个 UTF-16 字符中的任何一个,例如 U+A4xx Yi 音节或 U+01A4 LATIN SMALL LETTER OI。它不是 UTF-8 序列的有效第一个字节。如果您的一些用户在 Yi 中提交文本,您可能会遇到问题。

Python 3.x 文档, 7.2.3 Standard Encodings列出了 Python 标准库可以轻松处理的字符编码。以下程序可让您了解测试字符序列如何通过各种编码方式编码为字节:

>>> for e in ['iso-8859-1','iso-8859-15', 'utf-8', 'utf-16be', 'utf-16le', \
... 'cp1252', 'macroman']:
...     print e, list( euro.encode(e, 'backslashreplace'))

因此,作为一种权宜之计,令人满意的技巧,如果编码有任何问题,请考虑告诉您的用户输入“€”作为文本字段的第一个字符。然后您的系统应该将上述任何字节序列解释为编码线索,并丢弃它们。如果用户想以欧元字符开始他们的文本内容,他们以“€€”开始字段;第一个被吞下,第二个仍然是文本的一部分。

于 2012-11-18T06:18:32.447 回答