ISO-2022-JP

一种为电子邮件设计的日语编码,使用转义序列在字符集之间切换。

ISO-2022-JP 是一种为在电子邮件中收发日语文本而设计的字符编码。它具备用转义序列动态切换 ASCII 与 JIS X 0208 字符集的机制,并被汇总在 1993 年公开的 RFC 1468 中 (该 RFC 的类别是 Informational,并非正式的互联网标准)。在日本互联网的萌芽期,它作为用邮件处理日语的事实标准而广泛普及。

20 世纪 90 年代的互联网中,邮件的转发路径上存在大量只能通过 7 位 ASCII 的服务器。Shift_JIS 和 EUC-JP 属于 8 位编码,因此在通过这类路径时存在数据损坏的风险。ISO-2022-JP 作为所有字节都收在 7 位范围 (0x00-0x7F) 内的"7 位清洁"编码,解决了这一问题。

具体机制上,ISO-2022-JP 用转义序列 ESC $ B (0x1B 0x24 0x42) 切换到 JIS X 0208-1983 的日语模式,用 ESC ( B (0x1B 0x28 0x42) 返回 ASCII 模式。此外还一并定义了指向旧版 JIS X 0208-1978 的 ESC $ @ (0x1B 0x24 0x40),以及指向 JIS X 0201 拉丁字符集的 ESC ( J (0x1B 0x28 0x4A)。日语的各个字符用 2 个字节表示,ASCII 字符照常为 1 个字节。借助这种模式切换机制,就能在同一字节流中混排日语和英语。

实现时容易漏看的规定有 2 条。一条是"包含日语的行,必须在行末 (换行) 之前回到 ASCII 或 JIS X 0201 的拉丁字符集",另一条是"正文整体必须以 ASCII 结束"。忘记切回的文本,在按行处理的中继系统中,或在中途被分割、拼接的邮件正文中会丢失日语模式的状态,从那里往后就无法阅读。比起自己编写编码器,交给语言标准的库 (Python 的 iso2022_jp、Java 的 ISO-2022-JP 等) 更为安全。

另一个实务上的陷阱是可处理的字符仅限于 JIS X 0208 的范围。半角片假名 (JIS X 0201 的片假名) 在 ISO-2022-JP 中无法使用,带圈数字的①、㈱,以及俗称"梯子高"的髙这类 CP932 独有扩展的字符也在范围之外。如果发送方不加说明地塞入这些字符,接收方就会作为未定义字符丢失或出现乱码。虽然也有加入 JIS X 0212 的 ISO-2022-JP-1 (RFC 2237),以及进一步加入中文、韩文等的 ISO-2022-JP-2 (RFC 1554) 这样的扩展版,但支持情况参差不齐,现在回避这一限制的现实手段是迁移到 UTF-8。

现在的邮件系统已把 8 位支持作为标准,加上可以用 MIME 的 Content-Transfer-Encoding 使用 Base64 或 Quoted-Printable,因此用 UTF-8 收发已是一般做法。不过在日本的企业和政府机构中,为了维持与旧邮件系统的兼容性,仍有继续使用 ISO-2022-JP 的情况。

常见的问题是"乱码"。当把 ISO-2022-JP 的邮件当作 UTF-8 解释,或者转义序列在中途缺失时,就会显示出意义不明的字符串。其原因多见于邮件头的 Content-Type: text/plain; charset=ISO-2022-JP 未被正确设置。

与 Shift_JIS 和 EUC-JP 相比,ISO-2022-JP 虽然存在转义序列带来的额外开销,但另一方面具有 7 位清洁的优点。Shift_JIS 主要用于 Windows 环境,EUC-JP 主要用于 UNIX 环境,而 ISO-2022-JP 专用于邮件,曾经存在这样的分工。如今三者都在向 UTF-8 迁移。

从字符计数的角度来看,ISO-2022-JP 会因转义序列而增加字节数。例如"こんにちは" (5 个字符),若把切换到 JIS X 0208 模式和返回 ASCII 都算进去,共需 16 个字节。同一字符串在 UTF-8 中是 15 个字节,在 Shift_JIS 中是 10 个字节。这种额外开销不由字符数而由模式切换的次数决定,因此日语与英数字细碎交替排列的文面越是不利。例如"今日 10 時に A 社へ"会发生 6 次切换、达到 37 个字节,大幅超过 UTF-8 的 25 个字节和 Shift_JIS 的 19 个字节。编码不同会导致字节数不同这一点,在邮件的大小限制,以及把数据灌入按字节数设定上限的系统时,是重要的知识。

分享这篇文章