从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • 计算机简史

  • 数字电路

  • 计算机组成原理

    • 计算机组成原理(北大-陆俊林)

    • 字符编码入门

      • 简单聊聊计算机之中的时间
      • 简单聊聊字符编码
      • ASCII 字符表和说明
      • ASCII 的 SOH 的用处
      • 回车和换行
      • 汉字是怎么编码的
      • 简单聊聊 Unicode
      • 手持两把锟斤拷,口中疾呼烫烫烫
      • 数据库与编码
      • 编程语言与字符编码
      • URL 编码
      • Base64 编码
        • 为什么需要 Base64 编码
        • Base64 编码转换规则
        • Java 中的 Base64 编码
        • 如果不是 3 的倍数...
        • 参考
      • 字符编码小结
      • 一些有趣的代码注释
  • 操作系统

  • Linux

  • 计算机网络

  • 数据库

  • 编程工具

  • 装机

  • 计算机基础
  • 计算机组成原理
  • 字符编码入门
2023-02-06
目录

Base64 编码

# 22.Base64 编码

URL 编码是对字符进行编码,表示成 %xx ​的形式,而 Base64 编码是对二进制数据进行编码,表示成文本格式。

‍

# 为什么需要 Base64 编码

Base64 编码的目的是把二进制数据变成文本格式,这样在很多文本中就可以处理二进制数据。例如,电子邮件协议就是文本协议,如果要在电子邮件中添加一个二进制文件(比如图片),就可以用 Base64 编码,然后以文本的形式传送。

而且有时候一些路由器等硬件也不兼容二进制,或者一些网络协议不兼容,因此得转为字符形式。 ‍ 还有的时候,使用文本形式能减少一次 http 请求,提高效率:打开 google 的首页,就能看到某些样式中的图片不是一个资源地址,而是 base64 编码的字符串。通过 base64 来传输图片,然后浏览器解码该 base64,就能得到图片了。

注意:并不是什么图片都适合用 base64 来处理,因为图片越大,转换的 base64 的字符串就越长,对带宽的要求更高了。

​​​​ ‍

# Base64 编码转换规则

Base64 编码可以把任意长度的二进制数据变为纯文本,且只包含 A​ ~Z​,a​ ~z​,0​ ~9​、+​、/​、= ​这些字符。它的原理是把 3 字节的二进制数据按 6bit 一组,用 4 个 int 整数表示,然后把这个整数作为索引查表,得到对应的字符,最终得到编码后的字符串。

  • 6 位整数的范围总是 0​ ~63​,所以,能用 64 个字符表示:
  • 字符 A​ ~Z​对应索引 0​ ~25​,
  • 字符 a​ ~z​对应索引 26​ ~51​,
  • 字符 0​ ~9​对应索引 52​ ~61​,
  • 最后两个索引 62​、63​分别用字符 +​和 /​表示。 ‍ 索引表如下(摘自 RFC2045):

Table 1: The Base64 Alphabet

索引 对应字符 索引 对应字符 索引 对应字符 索引 对应字符
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v

14 O 31 f 48 w

15 P 32 g 49 x

16 Q 33 h 50 y

举个例子:3 个 byte 数据分别是 e4、b8、ad,按 6bit 分组得到 39、0b、22 和 2d(十六进制下):

┌───────────────┬───────────────┬───────────────┐
│      e4       │      b8       │      ad       │
└───────────────┴───────────────┴───────────────┘
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│1│1│1│0│0│1│0│0│1│0│1│1│1│0│0│0│1│0│1│0│1│1│0│1│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
┌───────────┬───────────┬───────────┬───────────┐
│    39     │    0b     │    22     │    2d     │
└───────────┴───────────┴───────────┴───────────┘
1
2
3
4
5
6
7
8
9

根据查表可得最后的字符是 5Lit​ 这四个字符。 ‍ 需要注意的是,根据 ASCII 编码,4 个字符占了 4*8=32 个 bit,比起原始的 bit 位数多了 1/3,传输效率会降低。字符越少,编码的效率就会越低。

如果把 Base64 的 64 个字符编码表换成 32 个、48 个或者 58 个,就可以使用 Base32 编码,Base48 编码和 Base58 编码。 ‍

# Java 中的 Base64 编码

Java 提供了不少类来对二进制数据进行 Base64 编码和解码。

例如对上述例子进行编码:

import java.util.Base64;

public class TestBase64{
  public static void main(String[] args) {
    byte[] input = new byte[]{ (byte)0xe4, (byte)0xb8, (byte)0xad};
    String base64Encoded = Base64.getEncoder().encodeToString(input);
    System.out.println(base64Encoded);  //5Lit
  }
}
1
2
3
4
5
6
7
8
9

‍ 解码:以补码形式输出结果

    byte[] output = Base64.getDecoder().decode("5Lit");
    System.out.println(Arrays.toString(output));  //[-28, -72, -83]
1
2

# 如果不是 3 的倍数...

如果输入的 byte[] ​数组长度不是 3 的整数倍肿么办?这种情况下,需要对输入的末尾补一个或两个 0x00​,编码后,在结尾加一个 = ​表示补充了 1 个 0x00​,加两个 = ​表示补充了 2 个 0x00​,解码的时候,去掉末尾补充的一个或两个 0x00 ​即可。

实际上,因为编码后的长度加上 = ​总是 4 的倍数,所以即使不加 = ​也可以计算出原始输入的 byte[]​。Base64 编码的时候可以用 withoutPadding() ​去掉 =​,解码出来的结果是一样的:

import java.util.Arrays;
import java.util.Base64;

public class TestBase642 {
    public static void main(String[] args) {
        byte[] input = new byte[] { (byte) 0xe4, (byte) 0xb8, (byte) 0xad, 0x21 };
        String b64encoded = Base64.getEncoder().encodeToString(input);
        String b64encoded2 = Base64.getEncoder().withoutPadding().encodeToString(input);
        System.out.println(b64encoded);
        System.out.println(b64encoded2);
        byte[] output = Base64.getDecoder().decode(b64encoded2);
        System.out.println(Arrays.toString(output));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

‍ 运行结果:

5LitIQ==
5LitIQ
[-28, -72, -83, 33]
1
2
3

因为标准的 Base64 编码会出现 +​、/ ​和 =​,所以不适合把 Base64 编码后的字符串放到 URL 中。一种针对 URL 的 Base64 编码可以在 URL 中使用的 Base64 编码,它仅仅是把 + ​变成 -​,/ ​变成 _​:

import java.util.Arrays;
import java.util.Base64;

public class TestBase643 {
    public static void main(String[] args) {
        byte[] input = new byte[] { 0x01, 0x02, 0x7f, 0x00 };
        String b64encoded = Base64.getUrlEncoder().encodeToString(input);
        System.out.println(b64encoded);
        byte[] output = Base64.getUrlDecoder().decode(b64encoded);
        System.out.println(Arrays.toString(output));
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13

‍ 运行结果:

AQJ_AA==
[1, 2, 127, 0]
1
2

# 参考

编码算法 - 廖雪峰的官方网站 (opens new window)

为什么要使用 base64 编码,有哪些情景需求? - 知乎 (opens new window)

Base64 编码原理与应用 (opens new window)

上次更新: 2025/6/3 17:50:46
URL 编码
字符编码小结

← URL 编码 字符编码小结→

最近更新
01
学点统计学:轻松识破一本正经的胡说八道
06-05
02
2025 年 5 月记
05-31
03
《贫穷的本质》很棒,但可能不适合你
05-27
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式