如何把 UTF-8 文本编码为 Base64
- 在 输入 · 文本 中输入或粘贴文本。字符集 已设为 UTF-8。
- Base64 显示在 输出 · Base64 中。工具下方的 输入 数值是 UTF-8 字节数;输入框上方的计数器按 JavaScript 的方式计算字符数,所以一个 emoji 算 2 个。
- 用于 URL 和令牌时,勾选 URL 安全(- _) 和 不填充(=);用于邮件或 PEM 时,选择一种 换行 方式。
- 复制输出,或将其下载为
base64.txt。
Base64 转 UTF-8 可以把结果还原为文本。
UTF-8 如何把字符变成字节
UTF-8 每个码位使用 1 到 4 个字节。ASCII 仍然是 1 个字节,所以英文文本在 UTF-8 和 ASCII 中的编码相同。其他字符都需要更多字节:
| 字符 | 码位 | UTF-8 字节 | Base64 |
|---|---|---|---|
A | U+0041 | 41 | QQ== |
é | U+00E9 | C3 A9 | w6k= |
€ | U+20AC | E2 82 AC | 4oKs |
日本語 | U+65E5 U+672C U+8A9E | 9 字节,每个 3 字节 | 5pel5pys6Kqe |
😀 | U+1F600 | F0 9F 98 80 | 8J+YgA== |
由于 Base64 还要在字节的基础上再增加三分之一,一句中文或日文从字符数到 Base64 字符数大约会增长到四倍,单个 emoji 则会变成 8 个字符。对于有长度限制的字段,请记住这一点;大小计算器 可以帮你计算。
emoji 序列和肤色
看起来是一个 emoji 的东西,往往是几个码位粘在一起。肤色是一个单独的修饰符,家庭或职业类 emoji 则用看不见的零宽连接符(U+200D)把几个人连在一起:
| Emoji | 码位数 | UTF-8 字节数 | Base64 |
|---|---|---|---|
| 😀 | 1 | 4 | 8J+YgA== |
| 👍🏽 | 2(竖大拇指 + 中等肤色) | 8 | 8J+RjfCfj70= |
| 👨👩👧 | 5(三个人 + 两个连接符) | 18 | 8J+RqOKAjfCfkanigI3wn5Gn |
在这样的序列中间截断 Base64 字符串或其解码后的字节,会留下残缺的字符,所以绝不要在任意字节处截断编码后的 UTF-8。
文本相同,字节不同:Unicode 规范化
有些字符在 Unicode 中有两种合法写法。é 可以是单个码位 U+00E9(组合形式,NFC),也可以是 e 后跟 U+0301 COMBINING ACUTE ACCENT(分解形式,NFD)。两者显示完全相同,但字节不同:
| 文本 | 形式 | 字节 | Base64 |
|---|---|---|---|
é | NFC | C3 A9 | w6k= |
é | NFD | 65 CC 81 | ZcyB |
naïve | NFC | 6 | bmHDr3Zl |
naïve | NFD | 7 | bmFpzIh2ZQ== |
Apple 较旧的 HFS+ 文件系统以分解形式存储文件名,而大多数键盘输入的是组合形式。如果你要比较 Base64 值、对它们签名或把它们用作键,请先做规范化。本工具会原样编码你粘贴的码位,不做规范化。
在代码中把 UTF-8 转为 Base64
在 JavaScript 中,TextEncoder 始终生成 UTF-8。当输入可能来自不同来源时,先做规范化:
const text = "e\u0301".normalize("NFC");
Buffer.from(text, "utf8").toString("base64"); // "w6k=" (Node.js)
new TextEncoder().encode(text); // Uint8Array [195, 169]
在浏览器中,TextEncoder 得到的字节可以交给 bytes.toBase64()(在支持的环境中,见 Uint8Array.toBase64),或者使用 JavaScript 页面 上基于 btoa 的辅助函数。
import base64, unicodedata
s = unicodedata.normalize("NFC", "nai\u0308ve")
base64.b64encode(s.encode("utf-8")).decode() # 'bmHDr3Zl'
文件和流式处理见 Python 中的 Base64。
常见问题
UTF-8 的 Base64 和普通 Base64 一样吗?
一样。Base64 编码的始终是字节;“UTF-8 转 Base64”只是说明了是哪些字节。对于纯 ASCII 文本,UTF-8 字节与 ASCII 字节相同,所以两种方式的输出完全一致。
为什么两个看起来一样的字符串,Base64 却不同?
Unicode 中有些字符可以用不止一种方式书写。作为单个码位的 é 是 w6k=,而 e 加组合重音符是 ZcyB。如果值必须一致,编码前先规范化为 NFC。
编码器会添加 UTF-8 字节顺序标记吗?
不会。输出直接从你的文本字节开始。如果使用方坚持要 BOM,Base64 就必须以 77u/ 开头,也就是字节 EF BB BF 的编码。
一个 emoji 占多少字节?
单个 emoji 码位在 UTF-8 中占 4 个字节。带肤色或组合成家庭的 emoji 由多个码位组成:👍🏽 是 8 个字节,家庭 👨👩👧 是 18 个。