Base64编码方式的介绍及其编码解码

news2025/1/10 12:16:05

一、Base64是什么

        Base64是一种用于将二进制数据编码为ASCII字符的编码方式,主要目的是为了能够在文本环境中传输和存储二进制数据。这种编码方式广泛应用于电子邮件、HTTP协议和其他需要传输或存储二进制数据的地方。

二、发明Base64编码的原因

        Base64编码的发明解决了在文本环境中传输和存储二进制数据的一系列问题,通过将二进制数据转换为可打印的ASCII字符,提高了数据传输的兼容性、安全性和可靠性。

以下是几点原因及其说明:

1、兼容性:

  • 文本系统的限制:许多应用系统(例如早期的电子邮件系统和某些协议)只能处理ASCII字符集,不能直接处理二进制数据。Base64通过将二进制数据转换为可打印的ASCII字符,使其能够在这些系统中传输和存储。
  • 避免数据损坏:在传输过程中,有些字符可能会被误解释为控制字符,从而导致数据损坏。Base64通过使用可打印的字符避免了这个问题。

2、标准化

  • 通用性:Base64提供了一种标准化的方法来编码和解码二进制数据,使得不同系统和应用程序之间可以互操作,而不需要担心底层数据格式的差异。
  • 广泛支持:Base64已经成为许多协议和文件格式的组成部分,并且得到了广泛的支持。例如,JSON Web Tokens(JWT)使用Base64来编码其负载部分。

3、易读性

  • 可打印字符:Base64编码后的数据仅包含字母、数字、“+”和“/”,以及填充字符“=”。这些字符都是可打印的,这使得编码后的数据更容易阅读和调试。
  • 避免特殊字符:Base64编码避免了使用可能在某些环境中有特殊含义的字符,例如空格、换行符和其他控制字符。

4、数据完整性

  • 减少变动风险:由于Base64编码后的字符串不包含非打印字符或控制字符,因此在传输或存储过程中,不太可能因为格式转换等原因导致数据变动或丢失。

5、实现简单

  • 编码和解码算法简单:Base64的编码和解码算法相对简单,可以很容易地在各种编程语言中实现。

三、Base64编码的编码原理

        首先,准备一个包含64个ASCII码的字符数组:['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/'],这64个字符不一定需要一样,但都是ASCII码表里可见字符(关于ASCII码表可参考:ASCII码表介绍),如下:

private static final char[] toBase64 = {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};

// 由于标准的Base64编码后可能出现字符+和/,在URL中就不能直接作为参数,所以把字符+和/分别变成-和_:
private static final char[] toBase64URL = {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
};

        接着,对二进制数据进行分割重组。因为一个字节是8位(bit)二进制组成的,共有2^9个数值(0-255),而我们上面定义的字符数组是64位的,所以需要重组成每6位(bit)二进制为一组。

        如上图,是3个字节(3x8=24bit)分割重组为4组(4x6=24bit),然后每一组的6位二进制可以转成一个数字(0-64,如,000000为0、000010为2等),这样我们得到4个数字作为索引,然后在上面定义的字符数组里获得相应的4个字符,就是编码后的字符串。

        例如,上面n1-n4分别为:000000、000010、000100、111111,则索引分别为:0、2、4、63,编码后字符串为ACE/。 

        如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节,Base64编码会在末尾补上2个或1个\x00字节(二进制00000000),使其达到3个字节(24bit),可以分为4组(4x6=24bit),再在编码后字符串的末尾加上2个或1个=号,表示补了多少字节,解码的时候,会自动去掉相应的\x00(其实有时候=号缺失也没事,程序会自动判断,取到足够数量二进制进行解码)。

        例如,要编码的二进制为1个字节,00100001(33,英文!号),分组后n1-n4分别为:001000、010000、000000、000000,则索引为8(2^3)、16(2^1),一共补上2个字节(16bit),所以编码后的字符串为IQ==。

import java.util.Base64;

public static void main(String[] args) throws Exception {
    System.out.println(String.format("%8s",Integer.toBinaryString("!".charAt(0))).replace(" ","0"));
    byte[] b = {33};
    System.out.println(new String(Base64.getEncoder().encode(b)));
    System.out.println(new String(Base64.getDecoder().decode("IQ==".getBytes(StandardCharsets.UTF_8))));
}

// 打印结果
二进制数据:00100001
编码后字符串:IQ==
解码后字符串:!

        所以,Base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%,好处是编码后的文本数据可以在邮件正文、网页等直接显示。

四、Base64编码的解码原理

        解码原理就是反过来,字符串(如:ACE/)根据定义的ASCII码字符数组,找到各自索引,转为N组二进制(6bit/组),再分割成M个字节(8bit/字节),末尾有2个或1个=号的,会相应减去对应数量的字节,最后解码出M-2或M-1个字节。

五、Java下Base64的编码与解码

1、sun.misc下的BASE64Encoder和BASE64Decoder

优缺点:

  • 这是JDK中自带的BASE64工具;
  • 但是所提供的Base64功能编码和解码的效率并不太高,而且在JDK1.9以后就不被维护了。
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
 
public class Base64Test {
    private static final BASE64Encoder ENCODE_64 = new BASE64Encoder();
    private static final BASE64Decoder DECODE_64 = new BASE64Decoder();
 
    @Test
    public void sun_misc_base64_T() {
        String text = "需要编码的数据";
        try {
            // 编码
            String encodedStr = ENCODE_64.encodeBuffer(text.getBytes("UTF-8"));
            System.out.println("encodedStr = " + encodedStr);
            // 解码
            String decodeStr = new String(DECODE_64.decodeBuffer(encodedStr), "UTF-8");
            System.out.println("decodeStr = " + decodeStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2、org.apache.commons.codec.binary下的Base64

优缺点: 

  • 与sun.misc方式比较,它的效率更高,代码更简洁;
  • 所有的JDK版本都支持
import org.apache.commons.codec.binary.Base64;

public class Base64Test {
    private static final Base64 BASE_64 = new Base64();
 
    @Test
    public void sun_misc_base64_T() {
        String text = "需要编码的数据";
        try {
            // 编码
            String encodedStr = BASE_64.encodeToString(text.getBytes("UTF-8"));
            System.out.println("encodedStr = " + encodedStr);
            // 解码
            String decodeStr = new String(BASE_64.decode(encodedStr), "UTF-8");
            System.out.println("decodeStr = " + decodeStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3、java.util下的Base64

优缺点:

  • java.util提供的Base64拥有更好的效能,实际测试编码与解码速度的话,比sun.misc套件提供的快至少11倍,比org.apache.commons.codec.binary提供的快至少3倍;
  • 但是,需要JDK1.8以后的版本才支持。
import org.junit.Test;
import java.util.Base64;
 
public class Base64Test {
    private static final Base64.Decoder DECODE_64 = Base64.getDecoder();
    private static final Base64.Encoder ENCODE_64 = Base64.getEncoder();

    @Test
    public void sun_misc_base64_T() {
        String text = "需要编码的数据";
        try {
            // 编码
            String encodedStr = ENCODE_64.encodeToString(text.getBytes("UTF-8"));
            System.out.println("encodedStr = " + encodedStr);
            // 解码
            String decodeStr = new String(DECODE_64.decode(encodedStr), "UTF-8");
            System.out.println("decodeStr = " + decodeStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1820548.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《转载》前苏联的三进制计算机Setun

1、苏联的三进制计算机概述 早在 1956 年,就需要创建一种可在大学和实验室中使用的实用数字计算机模型。为此,需要一种易于学习、可靠、廉价但同时高效、专为大规模使用而设计的小型计算机。 对这种机器的要求:运行速度必须等于每秒数百次操作…

破解发展难题 台山这家合作社以农业社会化服务助推乡村振兴

风吹稻田千层浪,眼下,台山四九镇的早稻长势喜人,沉甸甸的稻穗迎风而动,已进入破口抽穗的关键期,即将在6月底陆续迎来丰收。在台山市明华汇种养专业合作社管理的稻田里,合作社负责人梁明喜正仔细观察着稻苗的…

(代数:解一元二次方程)可以使用下面的公式求一元二次方程 ax2+bx+c0 的两个根:

(代数:解一元二次方程)可以使用下面的公式求一元二次方程 ax2bxc0 的两个根: b2-4ac 称作一元二次方程的判别式。如果它是正值,那么一元二次方程就有两个实数根。 如果它为 0,方程式就只有一个根。如果它是负值,方程式无实根。 编写程序,提示…

单点登录分析介绍

文章目录 1、单点登录解决方案1.1、后端保存登录状态1.2、token模式 2、user服务-登录接口2.1、UserController2.2、UserInfoServiceImpl2.3、载荷2.4、响应2.5、Redis Desktop Manager 1、单点登录解决方案 多个系统只有一个登录服务 1.1、后端保存登录状态 1.2、token模式 …

WordPress、Typecho 站点如何让 CloudFlare 缓存加速

众所周知 WordPress、Typecho 都是著名动态博客站点(一个最简单的判断依据就是都要依赖结合数据库),这类站点在 CDN 缓存上都有一个致命的缓存弊端就是动静态请求的区分,理论上要让 CDN 绕过所有的动态请求,缓存所有的静态请求,否则就会造成前端登录和非登录状态的混乱,…

聊聊分布式集群的基本概念

在当前主流的分布式架构中,各种各样的集群技术几乎成了任何想要提升系统稳定性和处理能力的团队的必备技能。虽然各种中间件和系统都有让人看似眼花缭乱的集群实现方案,但其背后仍然逃不过一些核心的技术概念,我会结合几个我比较熟悉的中间件…

java.nio.charset.UnmappableCharacterException

问题 java.lang.IllegalArgumentException: java.nio.charset.UnmappableCharacterException: Input length 1 解释为编码转换有问题 问题错在位置 非汉字存在 打包的时候就会报异常

怎么把wma格式转化为mp3格式?四种wma格式转成MP3格式的方法

怎么把wma格式转化为mp3格式?转换WMA格式音频文件为MP3格式是一个常见的需求,尤其是在我们希望在不同设备或平台上播放音频时。WMA格式虽然在Windows系统中较为常见,但在其他平台上的兼容性可能不如MP3格式。因此,将WMA转换为MP3是…

c#引用dll报错cs8370功能“本地函数特性“在c#7.3中不可用

cs8370:功能"本地函数特性"在c#7.3中不可用 解决方法: 代码放在form类里面

YOLOv5改进 | Head | 将yolov5的检测头替换为ASFF_Detect

💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 在目标检测中,为了解决尺度变化的问题,通常采用金字塔特征表示。然而,对于基于特征金字塔的单次检测器来…

NestJS学习笔记

一、安装NestJS CLI工具 环境检查 //查看node版本 node -v//查看npm版本 npm -v 安装nest/cli 使用npm全局安装nestjs/cli npm i -g nestjs/cli 查看nest版本 nest -v 结果如图: 创建nest项目 //命令行创建nest项目 nest new 【项目名】 VScode扩展下载 1、…

体验版小程序访问不到后端接口请求失败问题解决方案

文章目录 解决方案一:配置合法域名解决方案二:开发调试模式第一步:进入开发调试模式第二步:启用开发调试 注意事项结语 🎉欢迎来到Java面试技巧专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&…

银行业信息技术外包(ITO)深度解析:现状、挑战、业务分类与协同策略

一、引言 最近有朋友在咨询关于银行业信息技术外包(ITO)这块业务,同时也在网上看到了关于银行业信息技术外包(ITO)的相关信息,今天正好有时间,通过采集的相关信息结合自己的相关工作接触到的相关…

推挽与开漏输出

一般来说,微控制器的引脚都会有一个驱动电路,可以配置不同类型的数字和模拟电路接口。输出模式一般会有推挽与开漏输出。 推挽输出 推挽输出(Push-Pull Output),故名思意能输出两种电平,一种是推&#xf…

STM32开发过程中碰到的问题总结 - 1

文章目录 前言1. 怎么生成keil下可以使用的文件和gcc下编译使用的makefile2. STM32的时钟树3.怎么查看keil5下的编译工具链用的是哪个4. Arm编译工具链和GCC编译工具链有什么区别吗?5. 怎么查看Linux虚拟机是x86的还是aarch646. 怎么下载gcc-arm的编译工具链7.怎么修…

JavaScript的数组排序

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

css设置滚动条样式;滚动条设置透明

滚动条透明代码 .resizable-div {resize: both;/* 允许水平和垂直调整大小 */overflow: auto;/* 确保内容超出边界时出现滚动条 */ } /* 滚动条整体样式 */ .resizable-div::-webkit-scrollbar {width: 4px; /* 竖直滚动条宽度 */height: 4px; /* 水平滚动条高度 */ }/* 滚动条…

使用uniapp设置tabbar的角标和移除tabbar的角标

使用场景描述 在一进入到小程序的时候就要将用户在购物车中添加的商品总数&#xff0c;要以角标的形式显示在tababr中。 代码实现 //index.vue<script setup> import { onLoad } from dcloudio/uni-apponLoad(()>{uni.setTabBarBadge({index: 1,text: 5 //为了实现…

VBA实现关闭Excel自动计算,关闭屏幕刷新

Excel代码提速神器 涉及到提取表格大量数据操作&#xff0c;复制粘贴多个单元格时&#xff0c;尽量避免一个个单元格提取&#xff0c;或者一行行一列列提取数值&#xff0c;设计大量IO流操作非常浪费时间。尽量找出数据之间的规律&#xff0c;批量选中复制粘贴&#xff0c;找到…

【大数据】Spark使用大全:下载安装、RDD操作、JAVA编程、SQL

目录 前言 1.下载安装 2.RDD操作 3.JAVA编程示例 4.Spark SQL 前言 本文是作者大数据系列中的一文&#xff0c;专栏地址&#xff1a; https://blog.csdn.net/joker_zjn/category_12631789.html?spm1001.2014.3001.5482 该系列会成体系的聊一聊整个大数据的技术栈&…