“为什么俄语网页在你电脑上是一屏问号?为什么 JavaScript 里一个 emoji 的 length 是 2?为什么 AI 数不清 strawberry 里有几个 r?”这三个看似不相干的问题,答案都指向同一个地方:字符编码。Computerphile 频道请来英国最会讲计算机故事的 Tom Scott,用一段不到十分钟的短片《Characters, Symbols and the Unicode Miracle》,把人类如何把全世界所有文字塞进计算机这场持续六十年的战争讲得清清楚楚。本文以这条视频为骨架,补齐它没时间讲透的标准史、工程细节与那些著名的坑,并把它接到 2026 年最热的话题上——大模型时代的文本到底是怎么被机器“读”的。
| 项目 | 内容 |
|---|---|
| 视频标题 | Characters, Symbols and the Unicode Miracle(字符、符号与 Unicode 奇迹) |
| 频道 | Computerphile |
| 主讲人 | Tom Scott |
| 发布时间 | 2013 年(据频道页面) |
| 播放量 | 约 250 万+(据频道页面历史数据,本次撰写环境未能实时核验,请以频道页面为准) |
| 类型 | 计算机科学基础科普 / 字符编码史 |
※ 说明:本文撰写环境本次无法实时访问 YouTube 页面,以上数据为据频道页面与长期公开信息整理的量级参考,非实时数字。该视频发布十余年来持续被编程教学社区引用,属于“老视频、常青话题”——而大模型时代的 token 之争,又让字符编码这个老话题在近两年重新回到讨论中心。
Tom Scott 开场就把问题钉死:对计算机来说,屏幕上的 A、俄、あ、😀 全都只是数字。所谓“字符集”,就是一张“编号 ↔ 字符”的对照表;所谓“编码”,是规定这张表里的编号如何变成内存里的字节。理解了这一层,后面六十年的一切混战——ASCII、码页、Unicode、UTF-8——都只是“这张表怎么定、怎么存”两个问题的反复纠缠。这个开场是整条视频最值得学习的地方:它把一个令人生畏的技术话题压缩成了一个最小的心智模型。
1960 年代的美国工程师面对的问题是:怎么把英语打進计算机?答案是 ASCII——用 7 个比特,128 个编号,装下 26 个大写字母、26 个小写字母、10 个数字、常用标点和一串控制字符。A 是 65,小写 a 是 97,这个编号方案直到今天还在几乎所有编码里原样保留。Tom Scott 特别强调了一个细节:当时根本没有考虑英语之外的任何语言。这不是疏忽,而是时代的默认值——造计算机的是美国人,第一批用户也是美国人。
计算机很快普及到 8 位字节,128 之外还有 128 个空位。于是各语言社区开始了各自的圈地:西欧语言有 ISO 8859-1,俄语有 KOI8 和 CP1251,希腊语、土耳其语、希伯来语各有一套。同一个编号 200,在这张表里是 é,在那张表里是 щ,在第三张表里是 Ğ。文档从一台机器发到另一台机器,只要两边对不上“码页”,出来的就是一屏乱码——日语甚至给这种现象起了专有名词 mojibake(文字化け)。而中文、日文、韩文更惨:128 个空位连零头都不够,只能动用双字节编码,各国各搞一套互不兼容的方案,还催生了 Shift-JIS 里著名的反斜杠丢失问题。Tom Scott 用一句话总结这个时代:你的文档离开你的国家,就等于离开了你的编码。
视频的核心转折在这里:与其让每个语言社区各圈一块地,不如造一张真正的大表,把人类所有在用的文字系统全部收进来,每个字符分一个全球唯一的编号,这个编号叫码点,写作 U+XXXX。A 是 U+0041,е 是 U+0435,あ 是 U+3042——长得很像,编号完全不同。这就是 1991 年成立的 Unicode 联盟干的事。这张表设计容量是 17 个平面,共约 111 万个码点,常用文字全部住在最开始的“基本多文种平面”里。你手机里发的每一个 emoji,本质上也是一个 Unicode 码点——😀 的编号是 U+1F600,和字母 A 在同一张表里领身份证。
有了一张全球大表,还需要一个把码点存成字节的方案。视频里 Tom Scott 把最高的赞美留给了 UTF-8:它用 1 到 4 个字节的变长设计,让前 128 个码点(也就是整个 ASCII)保持单字节原样,英文世界的存量数据一个字节都不用改;而更大的码点则按规律展开成多字节序列。这个方案不是委员会的产物——1992 年,Unix 传奇人物 Ken Thompson 和 Rob Pike 在新泽西一家餐馆的餐垫上把它画了出来,Thompson 当晚就在 Plan 9 系统里实现了。Tom Scott 称之为"miracle":正是这个设计,让全世界最庞大的英文存量数据和最激进的全球字符大表无缝咬合,编码大战才得以真正收场。
视频因为时长限制大量省略了细节,把叙事放回真实的技术史料里,会发现每一步都有据可查。
ASCII:定型于美国标准协会 1963 年的 X3.4 标准,7 位编码是按电报码和打孔卡时代的工程约束算出来的,控制字符(如回车 CR、换行 LF)至今仍在解释 Windows 与 Unix 换行符差异的祖源问题。
码页时代:ISO 8859 系列(1987 年起)标准化了西欧及各区域 8 位编码;中国的 GB2312 发布于 1980 年,台湾 Big5 发布于 1983 年,日本则演化出 Shift-JIS 与 EUC-JP 并存的局面。“同一字节不同字符”的痛苦是整整一代程序员共同的集体记忆,Joel Spolsky 2003 年那篇著名长文《每个软件开发者都绝对必须知道的 Unicode 与字符集知识》开头那句“它不难,只是被讲复杂了”,针对的正是这个烂摊子。
Unicode 联盟:前身是 1987 年 Xerox 的 Joe Becker、Apple 的 Lee Collins 与 Mark Davis 发起的多语言编码讨论,1991 年正式成立联盟并发布 Unicode 1.0。Mark Davis 后来长期担任联盟主席,并曾任 Google 国际化首席工程师。联盟至今仍是会员制非营利组织,Apple、Google、Microsoft、Meta 等公司都在会员名单上——每年 9 月发布新版标准、新增字符,已经是固定节奏(Unicode 16.0 于 2024 年 9 月发布,一次新增了 5185 个字符)。
UTF-8:标志性文献是 Rob Pike 与 Ken Thompson 1993 年发表的 USENIX 论文,标题本身就充满野心——《Hello World or Καλημέρα κόσμε or こんにちは 世界》,用三种文字的“你好世界”宣示这张表的雄心。技术标准化进程则由 IETF 的 RFC 2044(1996)到 RFC 3629(2003)完成,后者把编码上限正式收敛到 U+10FFFF,也就是今天“1 到 4 字节”的最终形态。UTF-8 自同步的设计(任意字节都能判断自己是序列开头还是中间)意味着损坏不会扩散,这是它在工程上远胜其他方案的关键。
UTF-8 统治 Web 的三步:据 Google 软件工程师 Mark Davis 2008 年公布的搜索索引统计,UTF-8 超越所有旧编码成为 Web 主导编码;此后比例一路爬升到 98% 以上;2022 年 9 月,WHATWG 进一步宣布其标准体系(包括 HTML Living Standard)只支持 UTF-8,旧编码在标准层面退出历史舞台。从一家餐馆的餐垫到整个互联网的默认底色,这条路走了三十年。
emoji 的并入:emoji 并非 Unicode 联盟的发明,其源头是 NTT DoCoMo 员工栗田穰崇 1999 年为 i-mode 设计的 176 个小图标;2010 年 Unicode 6.0 才正式收录,2015 年 Unicode 8.0 引入菲茨帕特里克五级肤色修饰符。今天你跨平台发 emoji 不乱码,靠的是全球几大系统厂商在统一码点上达成的漫长妥协。
标准史上的著名风波:Unicode 也并非一路坦途。最著名的是谚文(韩文)风波——Unicode 1.0 与 2.0 对谚文音节采取了不同的排列方式,导致早期数据整体错位;2000 年代中期,国际学术界还曾集体抗议联盟试图收录超过 50 万个“组合式谚文音节”的方案(即 2005 年前后由多国学者联署的反对公开信)。这些风波说明:字符标准从来不只是技术问题,兼容性决策牵动着数十亿存量数据和文化归属,视频里那句轻描淡写的"miracle",背后是无数次近乎撕裂的谈判。
第一,视频没分清“字符集”和“编码方案”。这是理解一切编码问题最重要的一刀:Unicode 是字符集——负责给每个字符发编号;UTF-8、UTF-16、UTF-32 是编码方案——负责决定编号如何落到字节。说“这个文件是 Unicode 的”就像说“这个人是身份证的”——没有信息量。日常交流里没人较真,但写代码时混淆这两层,就会写出只在某些平台正确的字符串处理逻辑。
第二,“一个字符一个编号”本身是个善意的简化。真实世界复杂得多:é 既可以是一个码点 U+00E9,也可以是 e 加一个组合重音符 U+0301,视觉上一模一样,字节序列完全不同,这催生了 Unicode 规范化(NFC/NFD)这整一套规则;一家人形的 emoji 往往是“人 + 零宽连接符 ZWJ + 人 + ZWJ + 娃娃”的多码点序列;字符串“长度”至少有字节、码点、字形簇三个互相不一致的答案。Tom Scott 用“一个字符一个编号”完成了叙事,但工程上的坑几乎全部埋在简化被打破的地方。
第三,UTF-16 的历史债视频没提。Unicode 早期笃信 16 位足够(65536 个码点),Java、Windows、JavaScript 都在那个时代定型为 UTF-16 内部表示。后来码点空间扩到 17 个平面,UTF-16 只能用“代理对”硬补——一个增补字符占两个 16 位码元。后果直至今日:JavaScript 里 "😀".length 返回 2,字符串按码元切割会把 emoji 拦腰斩断,正则里的量词匹配常常错位。这是标准化历史上“早期容量估计失误、后期用兼容机制硬扛”的经典案例。
第四,UTF-8 也有代价,只是付得起。中日韩常用字在 UTF-8 里要 3 个字节,比 GBK、Shift-JIS 的双字节表示大约多 50% 存储;按字节截断字符串可能切出非法序列。历史上还有人利用“过长编码”(overlong encoding)构造绕过安全过滤的字节序列,迫使 RFC 3629 明确禁止。工程上它仍然是正确选择——用一点存储换全人类的互通,这笔账怎么算都划算——但"miracle"不等于零成本,视频没有展开这一面。
第五,统一码点反而打开了新的攻击面。全世界字符进了同一张表,长得一模一样的西里尔字母 а 和拉丁字母 a 就有了不同编号——同形异义字(homoglyph)攻击让钓鱼域名可以骗过最仔细的人眼,浏览器不得不用 Punycode 加特殊前缀(xn--)隔离非 ASCII 域名。2017 年前后 Chrome/Firefox 伪装域名(如 apple.com 的“李鬼版”)的公开演示让这一问题广为人知。字符统一是伟大的,但安全模型必须随之重建,这是视频完全没有触及的维度。
这条 2013 年的视频在 2026 年重新值得精读,是因为大模型带来了“文本表示”的又一次范式转移。GPT 系列及当今主流大模型普遍使用字节级 BPE 分词:模型并不直接看见 Unicode 码点,而是把 UTF-8 字节流切成一个个 token,每个 token 对应一张查到向量的小表。于是老问题换了新马甲重新上演:
其一,“AI 数不清 strawberry 里有几个 r” 的著名问题,根源不在模型笨,而在分词——strawberry 被切成两三个 token,模型看到的是 token 编号而非字母序列,数字母就像让你数一个压缩包里有几根电线。这和当年“同一字节不同码页”是同构的问题:表示层的有损压缩,向上泄漏成应用层的荒谬错误。
其二,非拉丁文字的“token 税”。同样一段意思,英文可能 10 个 token,中文日文可能要 20 个以上——因为训练语料里英文 token 切得粗、CJK 切得细。这直接影响 API 账单、上下文窗口的有效容量和推理延迟,堪称 BPE 时代的“码页不平等”。近年各家模型持续扩充多语言词表,本质上就是在重演 UTF-8 当年“让所有文字平权”的斗争,只不过战场从字节变成了 token。
其三,乱码与 U+FFFD 有了新受害者。爬取的网页若编码声明错误,字节流先变成一堆替换符 U+FFFD,再进入训练语料——模型学到的是被污染的文本。老一代工程师用十六进制查看器调试 mojibake 的功夫,在数据管道依然管用。
用这条视频的框架看就很清楚了:字符编码的历史,就是“人类的文字”与“机器的存储”之间反复寻找无损、高效、公平映射方案的历史。ASCII 解决了英语,码页搞砸了世界,Unicode 统一了编号,UTF-8 统一了字节——而 BPE 正在处理的是第四层:语义单元。每一层的欠账,最终都会以某种“AI 数不对字母”的形式被全社会看见。
启示一:一切默认 UTF-8,并且显式声明,不要靠猜。HTTP 响应头写明 charset=utf-8,HTML 放 <meta charset="utf-8">,文件保存为 UTF-8 无 BOM。特别提醒 MySQL 用户:数据库里的 utf8 是历史上只支持三字节的残缺实现,存不了 emoji,正确选项是 utf8mb4——这是无数人在用户昵称插入失败后才学到的教训。编码一旦在存储层选错,返工成本随数据量线性增长,而选对几乎零成本。
启示二:处理文本时,心里永远放着三层模型——字节、码点、字形簇。用户看到的“一个字”是字形簇,程序里的“一个字符”是码点,磁盘上的单位是字节,三者对不上是常态而不是异常。在 JavaScript 里数“用户感知长度”,用 [...str].length 或 Intl.Segmenter(ES2022 起内置),别用 str.length;做字符串截断、光标定位、输入校验时先想清楚你在哪一层操作。这一条习惯能提前消掉一整类只在某些用户手机上复现的诡异 bug。
启示三:调试乱码,别盯屏幕,看字节。乱码的本质永远是“同一串字节被两套编码各解释了一遍”。打开十六进制视图:看到 C3 A9 是被 UTF-8 解释过的 é;看到 EF BF BD 就是替换符 U+FFFD,说明上游已经解码失败;看到成片的 ? 说明转换时信息已被抹掉且不可恢复。判断“还能不能救回来”只看一点:原始字节是否还在,在,就有救;不在,神仙难为。养成先看字节再抱怨编码的习惯,你就能在一堆“乱码玄学”里成为那个十秒钟定位问题的人。
flowchart TD
A[电报与打孔卡时代<br/>7位ASCII 128字符] --> B[8位字节时代<br/>各国圈占后128位]
B --> C[码页地狱<br/>同一字节不同字]
C --> D[Unicode 1991<br/>每字符一个码点]
D --> E[UTF-16 早期路线<br/>代理对的历史债]
D --> F[UTF-8 1992<br/>餐馆餐垫上的设计]
F --> G[兼容ASCII自同步<br/>英文存量零改造]
F --> H[2008年登顶<br/>Web主导编码]
E --> I[JS与Java的坑<br/>length等于2的emoji]
H --> J[2022年WHATWG定音<br/>标准只留UTF-8]
J --> K[emoji全民时代<br/>多码点组合序列]
K --> L[大模型时代<br/>字节级BPE分词新战场]
Tom Scott 把"miracle"这个词送给了 Unicode,准确说应该送给 UTF-8 的设计克制:它没有要求世界推倒重来,而是让最旧的字节和最新的字符在同一个方案里和平共处。六十年来,从 128 个编号管天下的傲慢,到一张大表装下全人类的野心,再到餐馆餐垫上画出的变长编码,这条技术线每一次跃迁的共同主题是——让信息跨过语言、国界和设备的边界而不失真。今天当你向大模型提问时,你的每一个字仍要走完“字符 → 码点 → 字节 → token”这条完整流水线。看懂了这条流水线的来历,你就同时看懂了乱码从哪来、emoji 为什么占两个 length、AI 为什么数不对字母——以及下一次表示层革命来临时,该盯住什么。
本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
