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

Jon*_*ley 5 unicode encoding decoding

我正在将字节流解码为unicode字符,而不知道每百个发送者使用过的编码.

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

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

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

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

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

Jim*_*unt 4

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

\n\n

有一些非常简单的字符序列,只有某些用户才能输入。只有使用西里尔键盘和编码的用户会发现很容易键入“\xd0\x98\xd0\xbb\xd1\x8c\xd0\xb8\xcc\x81\xd1\x87”(Ilyich),所以你只需要区分支持西里尔文的编码,例如 UTF-8、UTF-16、iso8859_5 和 koi8_r。同样,您可以想出日语、中文和韩语字符序列来区分日语、简体中文、繁体中文和韩语系统的用户。

\n\n

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

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

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

\n\n

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

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

因此,作为一种权宜之计、令人满意的破解方法,如果编码存在任何问题,请考虑告诉用户键入 \'\xe2\x82\xac\' 作为文本字段的第一个字符。然后您的系统应该将上述任何字节序列解释为编码线索,并丢弃它们。如果用户希望以欧元字符开始文本内容,则可以以 \\'\xe2\x82\xac\xe2\x82\xac\' 开始字段;第一个被吞掉了,第二个仍然是文本的一部分。

\n