Base64 vs Hex 编码:数据格式对比

8 min2026年5月25日

Base64 vs Hex:核心权衡

Base64 和 Hex 编码的选择归结为一个问题:你需要紧凑性还是可读性?Hex 编码把每个字节转换为两个十六进制字符(00-FF),输出恰好是输入大小的 2 倍。Base64 把每 3 个字节转换为 4 个字符,输出是输入大小的 1.33 倍。对于 1 MB 文件:Hex 给你 2 MB,Base64 给你 1.33 MB。Base64 在大小上胜出;Hex 在简洁性上胜出。

Hex 更容易阅读和调试。每个字节精确映射到两个字符,所以你可以逐字节地视觉解析数据。十六进制字符串 "48656c6c6f" 明显是 5 个字节,你可以在 ASCII 表中查找每对(48=H, 65=e, 6c=l, 6c=l, 6f=o)。Base64 的 "SGVsbG8=" 更紧凑,但你无法直接看出单个字节——6 位分组跨越了字节边界。

两者都是文本安全编码——它们把任意二进制数据转换为可打印的 ASCII 字符。区别在于字符集:Hex 使用 16 个字符(0-9, a-f),Base64 使用 64 个字符(A-Z, a-z, 0-9, +, /)。每个符号包含更多字符意味着每个字符携带更多信息,这就是 Base64 更紧凑的原因。原理和十进制数字比二进制数字更短是一样的。

什么时候用 Hex 编码

哈希输出:SHA-256 产生 32 字节。作为 Hex,就是 64 个字符:"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"。每个哈希工具、每份文档、每个 API 都用 Hex 表示哈希值。这是通用惯例。我们的 hash-generator 工具默认输出 Hex,因为这是开发者期望看到和比较的格式。

调试二进制协议:当你查看网络数据包、文件头或内存转储时,Hex 是标准表示。Wireshark 显示 Hex。十六进制编辑器显示 Hex。PNG 文件的前几个字节是 "89504e47"——你可以记住这些魔数。在 Base64 中,同样的字节是 "iVBORw==",不太好认,也更难在文档中搜索。

颜色代码:CSS 颜色(#FF6B35)、MAC 地址(00:1A:2B:3C:4D:5E)和 UUID(550e8400-e29b-41d4-a716-446655440000)都用 Hex,因为每个组件干净地映射到字节。颜色是 3 字节(RGB),MAC 地址是 6 字节,UUID 是 16 字节。Hex 在视觉上保留了这种字节级结构。

小型二进制值:对于 100 字节以下的数据(加密密钥、短二进制标识符、协议头),Hex 的 2 倍开销可以接受,可读性优势值得。对于 32 字节的加密密钥,Hex 给你 64 个字符 vs Base64 的 44 个字符。20 个字符的差异很少有影响,但能通过数 64 个 Hex 字符来直观验证"没错,这是 32 字节"在开发时很有用。

什么时候用 Base64 编码

邮件附件(MIME):最初的使用场景。SMTP 是 7 位 ASCII,所以二进制附件必须用文本编码。Base64 的 33% 开销比 Hex 的 100% 开销在处理多兆字节文件时优势明显。你发过的每个邮件附件都用了 Base64。MIME 标准(RFC 2045)规定 Base64 每 76 个字符换行。

在 JSON/XML 中嵌入二进制:当 API 需要在文本格式中包含图片、文件或二进制数据块时,Base64 是标准做法。AWS S3 预签名 POST 策略使用 Base64 编码的 JSON。JWT 把载荷编码为 Base64url。HTML 中的 Data URI(data:image/png;base64,...)直接在标记中嵌入图片。33% 的开销是文本安全的代价。

文本环境中的大型二进制数据:对于几百字节以上且大小敏感的场景,Base64 胜出。100 KB 的图片用 Hex 是 200 KB;用 Base64 是 133 KB。在网络连接上,67 KB 的差异会累积。我们的 base64-encoder 工具处理最大 50 MB 的文件,并显示编码后的大小让你评估开销。

认证令牌和 Cookie:OAuth 令牌、会话 ID 和 API 密钥经常使用 Base64 或 Base64url 编码。紧凑的表示更适合放在 HTTP 头(实际大小限制约 8 KB)和 Cookie(每个 Cookie 限制 4 KB)中。Base64url(用 - 和 _ 替代 + 和 /)专门为 URL 安全场景设计,无需额外的百分号编码。

URL 编码:特殊情况

URL 编码(百分号编码)严格来说不是二进制到文本的编码——它是文本到文本的编码,让字符串在 URL 中安全使用。每个不安全的字节变成 %XX(百分号 + 两个十六进制数字)。空格变成 %20,& 变成 %26,一个中文字符(3 个 UTF-8 字节)变成 %E4%B8%AD。开销变化很大:ASCII 字母零开销,但全是特殊字符的字符串会膨胀三倍。

URL 编码是上下文相关的。在 URL 路径中,/ 是结构性的(不要编码)。在查询参数值中,/ 是数据(要编码)。在片段中,几乎不需要编码。这种上下文依赖性使 URL 编码与 Base64 或 Hex 根本不同,后者不管上下文统一编码所有内容。我们的 url-encoder 工具支持交互式编码并可选择上下文。

当 URL 编码遇到 Base64:如果你需要把 Base64 数据放在 URL 中,标准 Base64 的 + 和 / 字符需要百分号编码(%2B 和 %2F)。这就是 Base64url 存在的原因——它用 - 替代 + 、用 _ 替代 / 来避免双重编码。JWT 使用 Base64url 正是因为它们出现在 URL 和 HTTP 头中。对于要在 URL 中传输的数据,始终使用 Base64url(而非标准 Base64)。

典型场景的大小对比:编码二进制字符串 "Hello, World! 你好"(19 个 UTF-8 字节)。Hex:38 个字符。Base64:28 个字符。URL 编码:"Hello%2C%20World%21%20%E4%BD%A0%E5%A5%BD" = 41 个字符。URL 编码对二进制数据最差,因为它把每个字节编码为 3 个字符(%XX),同时让 ASCII 字母保持不变——开销完全取决于输入内容。

原始二进制:什么时候不该编码

有时候答案是"根本不要编码"。如果发送方和接收方都能处理二进制数据,文本编码只会增加不必要的开销和处理时间。Content-Type: application/octet-stream 的 HTTP 响应发送原始字节。WebSocket 二进制帧发送原始字节。multipart/form-data 的文件上传发送原始字节。Protocol Buffers 和 MessagePack 是二进制序列化格式,比 JSON+Base64 更小更快。

规则:只在传输通道要求文本时才使用文本编码(Base64、Hex)。邮件(SMTP)要求文本 → 用 Base64。JSON 载荷要求文本 → 二进制字段用 Base64。URL 参数要求文本 → 用 URL 编码或 Base64url。但 HTTP 正文、WebSocket 消息、gRPC 调用和文件 I/O 都原生支持二进制——对这些通道编码二进制数据是浪费带宽和 CPU。

性能对比:编码 1 MB 二进制数据。Base64 编码耗时约 2ms,产生 1.33 MB。Hex 编码耗时约 3ms,产生 2 MB。发送原始二进制耗时 0ms 编码时间,产生 1 MB。对于返回 5 MB 图片的 REST API,Base64 编码到 JSON 中需要 6.67 MB 传输 + 编解码 CPU 时间。作为单独的二进制响应只需 5 MB 传输 + 零编码开销。大载荷的选择显而易见。

混合方案:用 JSON 传元数据,用二进制传载荷。常见模式:API 返回 JSON,其中包含指向二进制资源的 URL,客户端单独获取。这给你结构化的元数据(标题、大小、content-type)用文本友好格式,加上高效的二进制传输用于实际数据。每个 CDN、对象存储服务和媒体平台都用这种模式。

对比表和决策指南

大小开销:原始二进制 = 0%。Base64 = 33%。Hex = 100%。URL 编码 = 0-200%(取决于内容)。对于大小敏感的应用(移动端 API、嵌入式系统、高吞吐服务),尽量用二进制传输减少编码开销,必须文本编码时用 Base64。

可读性:Hex 对开发者最可读(字节对齐,调试工具中常见)。Base64 紧凑但不透明(无法直观解析单个字节)。URL 编码对 ASCII 文本可读,但对二进制很丑。原始二进制没有十六进制查看器就不可读。根据开发和调试时是否需要人工检查数据来选择。

兼容性:URL 编码在 URL 中可用(这是定义)。Base64 在 JSON、XML、邮件和大多数文本环境中可用。Hex 在所有文本环境中可用,但很少是大数据的标准选择。原始二进制在 HTTP 正文、WebSocket、文件和二进制协议中可用,但不能用在 JSON 或 URL 中。让编码匹配你传输通道的要求。

我的决策树:传输通道支持二进制吗?→ 用原始二进制。是 URL 吗?→ 文本值用 URL 编码,二进制值用 Base64url。是 JSON/XML 吗?→ 二进制字段用 Base64。是调试/展示用?→ 用 Hex。是哈希或加密值?→ 用 Hex(惯例)。是邮件附件?→ 用 Base64(MIME 标准)。拿不准时,Base64 是二进制转文本场景中最安全的默认选择。

16 字节二进制数据(一个 UUID)的编码对比:

原始二进制:16 字节(无法作为文本显示)
Hex:        "550e8400e29b41d4a716446655440000"(32 字符)
Base64:     "VQ6EAOKbQdSnFkRmVUQAAA=="(24 字符)
Base64url:  "VQ6EAOKbQdSnFkRmVUQAAA"(22 字符,无填充)

1 KB 二进制数据的编码对比:

原始二进制:1,024 字节
Hex:        2,048 字符(+100%)
Base64:     1,368 字符(+33%)
URL 编码:   ~3,072 字符(+200%,最坏情况)

速度(编码 10 MB,Node.js M1 Mac):
  Buffer.toString('hex'):    ~8ms
  Buffer.toString('base64'): ~5ms
  不编码(原始):            ~0ms

选择编码格式时的常见错误

错误一:对已经是文本的数据做 Base64 编码。如果你有一个 JSON 字符串,在放入另一个 JSON 字段前对它做 Base64 编码,你白白增加了 33% 的开销。JSON 可以包含 JSON(作为转义字符串或嵌套对象)。只对真正的二进制数据(图片、文件、加密材料)做 Base64 编码。文本数据应该保持文本。

错误二:对大型二进制载荷使用 Hex。10 MB 文件用 Hex 是 20 MB——比 Base64(13.3 MB)或原始二进制(10 MB)多浪费了 10 MB。Hex 是用来展示和调试的,不是用来传输数据的。如果你的 API 在发送 Hex 编码的文件,换成 Base64 或二进制,立刻节省 33-50% 带宽。

错误三:在同一系统中混用编码格式。我见过有的 API 某些二进制字段返回 Hex,另一些返回 Base64,文档里也没说哪个是哪个。为你 API 中所有二进制数据选择一种格式并清楚地记录。一致性防止消费者把 Hex 当 Base64 解码(或反过来)然后得到乱码的 bug。

错误四:没考虑解码成本。编码和解码不是免费的——它们消耗 CPU 和内存。对于每秒处理数百万请求的高吞吐服务,Base64 编解码的累积成本可能很可观。如果你编码数据只是为了放进 JSON,然后在另一端立刻解码,考虑二进制协议(gRPC、MessagePack、Protocol Buffers)是否能完全消除这个开销。