字符编码

定义字符与比特序列对应关系的规则体系。由字符集 (定义包含哪些字符) 和编码方案 (定义如何转换为字节序列) 两个层次构成。

字符编码 (character encoding) 是计算机处理文字的根基技术。它规定了如何将人类阅读的「A」或「あ」转换为计算机可处理的数值。没有这套转换规则,文本的保存、传输和显示都无从谈起。

字符编码分成两个层次来理解最为清晰。第一层是「字符集」(character set),定义了要处理哪些字符。ASCII 为 128 个字符,JIS X 0208 为 6,879 个字符 (汉字 6,355 字与非汉字 524 字),Unicode 则涵盖 15 万字以上 (2025 年 9 月公开的 17.0 版为 159,801 个字符)。第二层是「编码方案」(encoding scheme),定义了字符集中的每个字符用什么样的字节序列来表示。同一个 Unicode 字符集之下并存着 UTF-8、UTF-16、UTF-32 等不同的编码方案,原因就在于此。排查乱码成因时,「该字符本来就不在字符集里」和「对编码方案的解释出了错」两种情况的处理办法完全不同,把这两层分开思考能更快找到根源。

日语的字符编码有着复杂的历史。1978 年制定了 JIS C 6226 (即后来的 JIS X 0208),制定当时收录 6,802 字,此后经过 1983 年、1990 年、1997 年的修订才形成现在的字数。以它为基础衍生出了 Shift_JIS (面向个人电脑制定,也称「MS 汉字码」)、EUC-JP (在 UNIX 系统中普及) 和 ISO-2022-JP (用于电子邮件)。三种编码方案用不同的字节序列表示同一个字符集,因此相互转换成了乱码的来源。

目前正在向 Unicode + UTF-8 统一。UTF-8 与 ASCII 完全向后兼容,英文文本为每字符 1 字节,日语为每字符 3 字节。凭借这种可变长设计,既能保持与 ASCII 圈系统的兼容性,又能处理世界各地的文字。根据 W3Techs 的使用状况调查,在能够判明字符编码的网站中,截至 2026 年 8 月有 99.0% 使用 UTF-8。新建系统选择 UTF-8 之外编码的理由,几乎只限于输入输出必须迁就既有系统的 Shift_JIS 或 EUC-JP 这一种情况。

在字数统计中,理解字符编码是必备前提。同一个「あ」,在 UTF-8 中占 3 字节,在 Shift_JIS 中占 2 字节,在 UTF-32 中占 4 字节。「字符数」与「字节数」相一致只发生在 ASCII 范围之内,含有日语字符的文本中两者并不一致。数据库的 VARCHAR(255) 究竟是「255 个字符」还是「255 个字节」,会随产品和设置而变,因此在决定位数之前要先确认按哪个单位计数。若在按字节计数的设置里存入日语,255 字节只能容纳 85 个字符左右,超出部分在保存时会被截断,或者直接登记失败。

实务上需要注意的是,与遗留系统对接时,至今仍会遇到必须转换为 Shift_JIS 或 EUC-JP 的场面。此时,Unicode 中存在而 Shift_JIS 中没有的字符 (表情符号、CJK 统一汉字扩展区的汉字、用于人名的异体字等) 无法转换,会被替换为「?」或「〓」(日语中称作「木屐记号」)。字符编码转换是一种可能伴随信息丢失的不可逆操作。把转换嵌入系统时,如果能将发生替换的字符作为错误检出,或者事先约定好替代写法的对照表,就可以避免姓名和地址在无人察觉的情况下以错字状态被保存的事故。

分享这篇文章