乱码
由于文本数据的编码与解码方式不一致,导致原本的字符显示为无意义的符号或其他字符的现象。
乱码 (mojibake) 是指写入文本时使用的字符编码与读取时使用的编码不匹配而产生的显示异常。例如,将以 UTF-8 保存的中文文本用 GBK 打开,「你好世界」可能变成「浣犲ソ涓栫晫」之类的乱码;反过来,用 UTF-8 打开 GBK 编码的文件,则会出现大量「�」(替换字符) 或完全不相关的汉字。
乱码发生的典型场景有三种。第一,文件保存时与读取时的编码不同;第二,数据库的连接字符集与表的字符集不一致;第三,HTTP 响应头中 Content-Type 指定的 charset 与 HTML 文件的实际编码不同。这三种情况的本质相同 - 写入方和读取方对编码的「约定」没有对齐。
从历史角度看,乱码问题在东亚地区尤为突出。中文环境中,GB2312、GBK、GB18030、Big5 等多种编码长期并存。大陆使用 GB 系列编码,台湾和香港使用 Big5,日本则有 JIS、Shift_JIS、EUC-JP 三种主要编码。在电子邮件和早期网页中,由于编码声明缺失或不正确,乱码几乎是家常便饭。
如今 UTF-8 已成为 Web 的事实标准,乱码的发生频率大幅降低。根据 W3Techs 的调查,超过 98% 的网站采用 UTF-8 编码。然而,在与遗留系统对接、CSV 文件交换 (Excel 默认期望带 BOM 的 UTF-8)、旧数据库迁移等场景中,乱码问题并未完全消失。
防止乱码的实务要点非常明确:文件统一使用 UTF-8 (无 BOM) 保存;数据库字符集使用 utf8mb4;HTTP 响应明确声明 Content-Type: text/html; charset=UTF-8;需要用 Excel 打开的 CSV 文件则输出为带 BOM 的 UTF-8。只要贯彻这些原则,在现代开发环境中就能避免绝大多数乱码问题。
从字符计数的角度来看,乱码文本的可见字符数与实际字节数会严重偏离。例如,将 UTF-8 编码的中文文本按 Latin-1 解释,一个汉字会膨胀为 3 个字符,导致计数结果接近实际值的 3 倍。因此,准确的字符计数的前提是文本编码被正确识别。