Page 1 of 1

如何存储 emoji 和特殊字符?字符集选择是什么?

Posted: Tue May 20, 2025 11:24 am
by muskanislam99
存储 Emoji 和各种特殊字符是现代消息传递应用必须面对的挑战,因为它们在全球范围内支持不同的语言、文化和表情符号。解决这个问题的核心是采用正确的字符集编码,尤其是在数据库层面。

1. 核心解决方案:UTF-8 Unicode 编码
为了正确存储 Emoji 和所有可能的特殊字符(包括各种语言的文字,如中文、日文、阿拉伯文等),WhatsApp 会毫无疑问地使用 UTF-8 (Unicode Transformation Format - 8-bit) 作为其主要的字符集编码。

什么是 UTF-8?
UTF-8 是一种变长字符编码,它能够表示 Unicode 字符集中的所有字符。Unicode 是一个国际标准,旨在为世界上所有书写系统中的每个字符提供一个唯一的数字(码点)。
UTF-8 的“变长”特性意味着它使用 1 到 4 个字节来编码一个 Unicode 字符。对于 ASCII 字符(英文字母、数字、基本符号),它使用 1 个字节,与 ASCII 兼容;对于其他语言字符和 Emoji,它使用更多字节。
为什么选择 UTF-8?
全面覆盖: Unicode 包含了世界上几乎所有的书写系统字符,以及大量的符号、数学符号、表情符号(Emoji)。UTF-8 能够忠实地编码这些所有字符。
兼容性: 它与 ASCII 兼容,这意味着现有的 ASCII 文本可以直接被解释为 UTF-8,而无需转换。
节省空间: 对于以拉丁字母为主的文本,UTF-8 比固 多米尼加共和国 whatsapp 数据库 定长度的 UTF-16 或 UTF-32 更节省空间。
互操作性: UTF-8 是 Web 和现代软件开发中最广泛使用的字符编码,具有极佳的跨平台和跨系统互操作性。
2. 数据库层面配置:utf8mb4
在数据库中,尤其是 MySQL 这样的关系型数据库,仅仅设置 UTF-8 可能不足以完整支持所有 Emoji。这是因为 MySQL 早期的 utf8 字符集实现实际上只支持每个字符最多 3 个字节,而某些 Emoji(特别是较新的和组合 Emoji)需要 4 个字节。

正确的选择是:utf8mb4。
utf8mb4 是 MySQL 对完整 UTF-8 的实现,它支持每个字符最多 4 个字节的编码,因此可以完全存储所有 Unicode 字符,包括所有 Emoji。
配置范围:
数据库实例级别: 整个数据库服务器的默认字符集和排序规则应设置为 utf8mb4。
数据库级别: 每个数据库的字符集应设置为 utf8mb4。
表级别: 每张表(特别是存储消息内容、用户名、群名称等文本的表)的字符集应设置为 utf8mb4。
列级别: 存储文本内容的列(如 Messages.content,Users.display_name,Groups.group_name,Payments.description 等)的字符集应明确设置为 utf8mb4。
连接级别: 客户端应用程序与数据库的连接字符集也必须设置为 utf8mb4,确保数据在传输过程中不被破坏。
3. 消息内容存储的数据类型
即使选择 utf8mb4,消息内容本身在存储时通常不会直接以可读的 VARCHAR 或 TEXT 形式存储,因为 WhatsApp 的端到端加密特性。

加密后的消息内容:
如前所述,用户发送的文本消息(包括其中的 Emoji)在发送方设备上加密后,会变成一串二进制数据。
数据库中的 Messages.content 字段将使用 BLOB 类型来存储这些加密后的二进制数据。BLOB 不关心其内部是什么字符,它只存储字节流,这完美符合加密消息的需求。
其他文本字段:
对于那些不涉及端到端加密但可能包含 Emoji 或特殊字符的文本字段,例如:
Users.display_name (用户显示名称)
Groups.list_name (群名称)
Groups.group_description (群描述)
UserPrivacySettings.about_text (用户“关于”信息)
这些字段应该使用 VARCHAR 或 TEXT 类型,并且其字符集明确设置为 utf8mb4。
4. 排序规则 (Collation)
除了字符集,排序规则(Collation)也需要考虑。它定义了字符串的比较和排序规则(例如,是否区分大小写、重音,以及特定语言的字母顺序)。

通常会选择一个通用的、不区分大小写和重音的 utf8mb4_unicode_ci 或 utf8mb4_general_ci。
对于需要精确、语言特定排序的场景,可以选择更具体的排序规则。
总结
WhatsApp 为了支持全球用户使用各种语言和 Emoji,会采取以下存储策略:

核心编码: 全面采用 UTF-8 Unicode 编码。
数据库配置: 在数据库(特别是 MySQL)中,使用 utf8mb4 字符集,确保对所有 4 字节 Emoji 的完整支持,并应用于数据库、表和列级别。
消息内容: 由于端到端加密,实际的加密消息内容将存储在 BLOB 类型字段中,作为原始二进制数据。
其他文本字段: 不涉及加密的文本字段(如用户名、群名称)则使用 VARCHAR 或 TEXT 类型,并配置为 utf8mb4 字符集,以直接存储 Emoji 和特殊字符。
这种组合方式确保了所有字符的正确存储、检索和显示,同时维护了加密消息的完整