应该发送哪些字符串来消除他们使用的字节编码的歧义?

时间:2012-08-21 17:24:25

标签: unicode encoding decoding

我正在将字节流解码为unicode字符,而不知道每百个发件人使用的编码。

许多发件人在技术上并不精明,并且无法告诉我他们正在使用什么编码。它将由他们用于生成数据的工具链的偶然事件决定。

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

我是否可以要求所有发件人向我发送一个特定的字符串,这些字符将明确说明每个发件人使用的编码?

我知道有些库使用启发式方法来猜测编码 - 我也会追逐它,作为运行时回退,但首先我想尝试确定正在使用的编码,如果我可以。

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

1 个答案:

答案 0 :(得分: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的欧洲支持继承者。
  • U.S。用户可能不知道如何键入欧元字符。 (好吧,那太苛刻了.3%的人都知道。)

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

Python 3.x documentation, 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'))

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