内容提要
本文介绍了字符编码的发展,从最初的ASCII码表到统一的Unicode编码,解决了乱码问题。还讨论了字符编码到字体的转换以及处理复杂编码的方法。
延伸解读
从乱码到统一:Unicode 如何终结编码混乱
文章回顾了早期各国自定码表(如 GBK、Shift-JIS)导致的乱码问题,例如日文文本在 GBK 环境下显示为“偙傫偵偪偼”。Unicode 通过为所有语言字符分配唯一码点,从根本上解决了跨地区文本交换的障碍。这一统一过程不仅简化了软件开发,也使得多语言网页和国际化应用成为可能。
UTF-8 与 UTF-16:编码选择背后的权衡
Unicode 码点可通过不同方案编码。UTF-8 采用变长字节(1-4 字节),兼容 ASCII,适合存储和网络传输;UTF-16 固定使用 16 位单元,但需代理对表示 BMP 以外的字符,且不兼容 ASCII。文章指出 JavaScript 字符串在内存中使用 UTF-16,这解释了为何某些字符操作(如 length)会返回意外结果。
字体与字形:同一码点为何显示不同
字体负责将编码映射为可视字形。文章提到,由于 Han unification,同一码点在不同地区可能呈现不同字形(如“关”在简繁日韩中的差异)。浏览器根据 lang 属性选择默认字体,但若显式指定某语言字体(如微软雅黑),则可能强制使用该字形。字体格式如 ttf、otf、woff2 各有特点,影响渲染效果与加载性能。
编程中的字符操作陷阱:代理对与组合字符
文章通过 JavaScript 示例揭示,charAt 和 charCodeAt 以 UTF-16 代码单元为单位,处理代理对(如“𪜹”)或组合 Emoji(如👨👩👧👦)时会返回不完整结果。codePointAt 能返回完整码点,但对组合字符仅返回首个码点。开发者需注意这些反直觉行为,尤其在处理非 BMP 字符或 Emoji 时,避免错误假设字符串长度或字符边界。
Q&A
什么是字符编码,最初的字符编码是什么?
字符编码是数值与字符的对应关系,最初的字符编码是ASCII码表。
Unicode解决了什么问题?
Unicode统一了所有编码,解决了不同编码导致的乱码问题。
UTF-8和UTF-16有什么区别?
UTF-8支持变长编码,而UTF-16则固定为16位。
为什么不同地区的同一码点可能有不同的字形?
因为同一码点在不同地区可能有不同的字形,这种情况称为汉字统一。
如何从编码转换到显示字符?
从编码到显示字符需要字体的支持,字体维护编码到文字的映射。
JavaScript中如何处理Unicode字符?
JavaScript使用UTF-16编码,提供charAt、charCodeAt和codePointAt方法处理字符。