表情转 Unicode 转换器
粘贴一个表情,或一整句带表情的文字,即可得到开发者需要的所有格式:Unicode 码位、HTML 实体、CSS 和 JavaScript 转义、Python,以及原始 UTF-8 字节。反向转换同样可用。所有处理都在你的浏览器中完成,长度计数器还能告诉你,为什么一个表情在一种语言里算七个字符,在另一种环境里却占二十八个字节。
- 肉眼所见字符数
- 3
- 码位数(Python len)
- 6
- UTF-16 单元数(JS .length)
- 10
- UTF-8 字节数
- 22
| Unicode 码位 | U+1F44D U+1F3FD U+2764 U+FE0F U+1F1EF U+1F1F5 | |
|---|---|---|
| HTML 实体(十六进制) | 👍🏽❤️🇯🇵 | |
| HTML 实体(十进制) | 👍🏽❤️🇯🇵 | |
| CSS content | \1F44D \1F3FD \2764 \FE0F \1F1EF \1F1F5 | |
| JavaScript (ES6) | \u{1F44D}\u{1F3FD}\u2764\uFE0F\u{1F1EF}\u{1F1F5} | |
| UTF-16(Java、C#、JSON) | \uD83D\uDC4D\uD83C\uDFFD\u2764\uFE0F\uD83C\uDDEF\uD83C\uDDF5 | |
| Python | \U0001F44D\U0001F3FD\u2764\uFE0F\U0001F1EF\U0001F1F5 | |
| UTF-8 字节 | F0 9F 91 8D F0 9F 8F BD E2 9D A4 EF B8 8F F0 9F 87 AF F0 9F 87 B5 | |
| URL 编码 | %F0%9F%91%8D%F0%9F%8F%BD%E2%9D%A4%EF%B8%8F%F0%9F%87%AF%F0%9F%87%B5 |
八个表情,四种不同长度
下面每一行在屏幕上都只是一个表情。其余各列是不同编程语言和数据库计出的长度,由与上方工具相同的转换器算出。
| 表情 | 码位 | 可见 | Python | JavaScript | UTF-8 字节 |
|---|---|---|---|---|---|
| 😀单个码位 | U+1F600 | 1 | 1 | 2 | 4 |
| ❤️文字符号加样式选择符 | U+2764 U+FE0F | 1 | 2 | 2 | 6 |
| 👍🏽表情加肤色 | U+1F44D U+1F3FD | 1 | 2 | 4 | 8 |
| 🇯🇵两个区域指示符字母 | U+1F1EF U+1F1F5 | 1 | 2 | 4 | 8 |
| 👩💻用零宽连接符拼接 | U+1F469 U+200D U+1F4BB | 1 | 3 | 5 | 11 |
| 1️⃣数字、选择符和键帽 | U+0031 U+FE0F U+20E3 | 1 | 3 | 3 | 7 |
| 🏴标签序列 | U+1F3F4 U+E0067 U+E0062 U+E0073 U+E0063 U+E0074 U+E007F | 1 | 7 | 14 | 28 |
| Emoji 18.0(2026) | U+1FAFA | 1 | 1 | 2 | 4 |
为什么一个表情可以有七个字符长
码位是 Unicode 分配的编号,一个表情可以由多个码位组成。苏格兰旗就是最典型的例子:一面黑旗、五个拼出 gbsct 的隐形标签字母,再加一个取消标签,总共七个码位。JavaScript 用 UTF-16 存储文本,U+FFFF 以上的字符各占两个单元,所以同一面旗帜的 .length 是 14。UTF-8 为每个这样的码位花费四个字节,所以它在数据库中占 28 个字节。只有一个数字与人眼看到的一致,而大多数代码偏偏从不计算它。在 JavaScript 中,用 Intl.Segmenter 并把 granularity 设为 grapheme 来计数;在 Python 中,第三方 regex 模块的 \X 模式可以做同样的事。
在 MySQL 中存储表情而不变成问号
如果表情保存后变成了 ????,那几乎可以肯定该列用的是 MySQL 的 utf8 字符集,它名不副实,每个字符最多只存三个字节。U+FFFF 以上的每个表情都需要四个字节,所以插入要么失败,要么丢失数据。解决方法是 utf8mb4:用 ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 转换表,并确保连接本身也使用 utf8mb4,因为即使表设置正确,经过 utf8 连接的文本仍会被弄乱。MySQL 8.0 已把 utf8mb4 设为默认值,所以这个问题主要出现在升级而来、而非全新创建的旧数据库上。
HTML 实体、CSS 与末尾的空格
在以 UTF-8 提供的页面上(几乎所有页面都是如此),你可以直接把表情粘贴进 HTML;只有当模板或邮件系统会弄乱原始字符时,才需要 👍 这样的实体。CSS 则更讲究。在 content 属性中,\1F44D 这样的转义会一直延续到第一个非十六进制字符为止,所以如果下一个字符可能被当成十六进制,就必须用一个空格结束转义。这个空格会被吞掉,不会显示出来。我们的 CSS 一行总会在码位之间加上它,所以带肤色的点赞会输出为 \1F44D \1F3FD,中间那个空格是有意保留的。
为什么 X 把每个表情都算作两个字符
字数限制是计数结果出现分歧的另一个地方。X 的开源计数库把大多数表情按两个字符计入 280 字的上限,不管它们由什么组成,所以 👍 和 👩💻 占用的额度相同,尽管前者只有一个码位,后者有三个。短信更苛刻:只要有一个表情,整条消息就会被迫改用 UCS-2 编码,单条短信的上限从 160 个字符降到 70 个。如果某个表单、数据库列或社交平台拒绝了看起来很短的文字,上面的长度表通常能说明原因。
表情术语表:码位、连接符与选择符Slack、Discord 和 GitHub 的表情短代码可复制的全部表情
关于表情码位的问题
笑脸表情的 Unicode 是什么?
😀 咧嘴笑脸是 U+1F600。HTML 中写作 😀,CSS 中写作 \1F600,JavaScript 中写作 \u{1F600} 或旧式的 \uD83D\uDE00,Python 中写作 \U0001F600。把其他任意表情粘贴到转换器中即可获得它的代码。
为什么一个表情有两个码位?
许多表情都是序列。❤️ 是爱心符号 U+2764 加样式选择符 U+FE0F,👍🏽 是点赞加肤色,旗帜则是两个字母。你的设备会把整个序列画成一张图。
\u{1F600} 和 \uD83D\uDE00 有什么区别?
它们是同一个表情。\u{1F600} 直接写出码位,适用于现代 JavaScript。\uD83D\uDE00 是 UTF-16 代理对,对于 U+FFFF 以上的字符,旧版 JavaScript、Java、C# 和 JSON 只接受这种形式。
一个表情占多少字节?
在 UTF-8 中,U+FFFF 以上的每个码位占四个字节,所以 😀 这样的简单表情是四个字节。序列会累加:👍🏽 是 8 个字节,👩💻 是 11 个,苏格兰旗是 28 个。
这个转换器会把我的文字发送到别处吗?
不会。转换完全在你的浏览器中用 JavaScript 完成。你输入或粘贴的任何内容都不会被上传或存储。
