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

一、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();
        }
    }
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

猫狗识别(超详细版)(py代码)

猫狗识别(一) 二、视频识别 用OpenCV和Tkinter构建的视频识别猫狗的应用程序。它允许用户从文件对话框中选择一个视频文件,然后在Tkinter窗口中播放视频,并使用Haar级联分类器实时检测视频中的猫和狗。 1.导入所需的库&#xff…

QT--DAY1

不使用图形化界面实现一个登陆界面 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {//设置窗口标题this->setWindowTitle("登录界面");//设置窗口大小this->resize(535,410);//固定窗口大小this->setFixedSize(535,410)…

北京多商入驻app开发项目的主要优势及功能

多商入驻app开发项目的定义 随着电子支付技术的不断成熟,全国各地的消费者通过网络在线上购物的频率越来越高,为此,多商入驻app开发项目应用而生。各商家也纷纷开始申请入驻商城平台,开设自己的店铺。 图片来源:unspl…

MAVEN-SNAPSHOT和RELEASE

一、快照版本SNAPSHOT和发布版本RELEASE区别 快照版本SNAPSHOT和发布版本RELEASE区别-CSDN博客 在使⽤maven过程中,我们在开发阶段经常性的会有很多公共库处于不稳定状态,随时需要修改并发布,可能⼀天就要发布⼀次,遇到bug时&am…

网络编程(三)UDP TFTP协议

文章目录 一、 UDP(一)概述(二)流程 二、收发函数(一)recvfrom(二)sendto 三、实现一个简单的udp服务端和客户端四、实现tftp客户端协议 一、 UDP (一)概述 …

vue 中多个表单元素控一个校验规则

1. 场景一 <el-form-itemlabel"确认时长方式"prop"preSubResourceDurationDay" ><div class"confirmDurationDay">最晚使用日期前<el-input-numberv-model"form.preSubResourceDurationDay":precision"0"cla…

为什么需要负样本

假如我们只有正样本&#xff0c;模型在最开始训练的时候都是错误的&#xff0c;随着模型的迭代&#xff0c;准确率逐渐从0到1&#xff0c;最终将所有的样本都判别成正样本&#xff0c;也就是都在线的上方。 但真实的场景中有正有负&#xff0c;例如我们要做一个猫狗分类器&…

jsp 实验20

三、源代码以及执行结果截图&#xff1a; NewFile.jsp <% page import "java.io.*" %> <% page contentType"text/html" %> <% page pageEncoding "utf-8" %> <jsp:useBean id"english" class "web.Engli…

nginx配置https协议(测试环境)

第一步申请证书 首先申请证书这一步&#xff0c;晚上有很多种方式实现&#xff0c;可以自己用算法实现&#xff0c;也可以找在线生成的网站&#xff0c;我这里使用了在线网站 https://www.toolhelper.cn/SSL/SSLGenerate 第二步将证书放到对应的目录下 这里我们主要用cert.pe…

基于JSP技术的大学生校园兼职系统

开头语 你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;可以通过文末的联系方式找到我。 开发语言 JSP 数据库 MySQL 技术 JSP JavaBeans 工具 MyEclipse、Tomcat、Navicat 系统展示 首页 学生登录界面 招聘信息界面 论坛中心界面 摘…

028、工具_Pipeline

Redis客户端执行一条命令分为如下四个过程: 1)发送命令 2)命令排队 3)命令执行 4)返回结果 其中1)+4)称为Round Trip Time(RTT,往返时间)。 Pipeline(它能将一组Redis命令进 行组装,通过一次RTT传输给Redis,再将这组Redis命令的执行结果按顺序返回给客户端,图3-…

2.6-5V/2.5A升9V12V18V方案 升压恒压IC 低功耗小家电芯片-H6391惠海

H6391升压恒压IC是一款适用于多种小家电和电子设备的电源管理升压恒压芯片。其设计特点有低功耗、高效率以及灵活配置等方面&#xff0c;以下是针对其特性的详细分析&#xff1a; 宽输入电压范围&#xff1a;H6391支持2.6-5V的输入电压范围&#xff0c;这使得它适合于由单节锂电…

【六】Linux安装部署Nginx web服务器--及编写服务器启动脚本

一、部署安装nginx 1、查看nginx是否安装依赖包 [rootlocalhost ~]# rpm -q zlib-devel pcre-devel package zlib-devel is not installed package pcre-devel is not installed 2、若没有则安装nginx 依赖包 [rootlocalhost ~]# yum -y install zlib-devel* pcre-dev…

线上3d数字艺术展让您在市场竞争中更具优势

在传统电商中&#xff0c;高昂的引流成本和激烈的行业竞争让获客变得尤为困难。随着web3技术的发展和覆盖&#xff0c;产品交互3D数字云展厅融合先进的web3D开发技术&#xff0c;构建了一个沉浸式数字空间&#xff0c;让客户随时随地通过电子设备进入展厅&#xff0c;享受自由浏…

vue 生命周期 钩子函数 keep-alive activated deactivated

一、activated deactivated 在被keep-alive包含的组件/路由中&#xff0c;会多出两个生命周期的钩子:activated 与 deactivated。在 2.2.0 及其更高版本中&#xff0c;activated 和 deactivated 将会在树内的所有嵌套组件中触发。activated在组件第一次渲染时会被调用&#x…

路虽远,行则将至 - 附暑期实习、秋招历程经验分享

前言 大家好 许久没有时间静下心来打开编辑器写文章了 忙碌暂过&#xff0c;难得一闲时 求学三年&#xff0c;终到离别时 回忆过往&#xff0c;枯燥且多彩 有一点经验&#xff0c;以文字形式分享&#xff0c;希望帮助到大家 可能是这段时间事多且杂&#xff0c;加上很长一…

日本2024年最受欢迎的转职行业是IT 通信

2024年有关机构针对超1000名人力资源专业人士进行了“推荐转职行业”的调查。结果显示&#xff0c;日本目前最受欢迎的转职行业是 1、“IT/通信行业”&#xff08;45.9%&#xff09;&#xff0c; 2、其次是“互联网/广告/游戏”&#xff08;31.9%&#xff09;&#xff0c; 3、“…

NFTScan 正式上线 Sei NFTScan 浏览器和 NFT API 数据服务

2024 年 6 月 12 号&#xff0c;NFTScan 团队正式对外发布了 Sei NFTScan 浏览器&#xff0c;将为 Sei 生态的 NFT 开发者和用户提供简洁高效的 NFT 数据搜索查询服务。NFTScan 作为全球领先的 NFT 数据基础设施服务商&#xff0c;Sei 是继 Bitcoin、Ethereum、BNBChain、Polyg…

UML类图之间的关系与对应的代码关系

UML类图之间的关系与对应的代码关系 1. 依赖关系1.1 图解1.2代码实现 2. 关联关系2.1图解2.2代码实现 3. 聚合关系3.1图解3.2代码实现 4. 组合关系4.1图解4.2代码实现 5. 泛化关系5.1图解5.2代码实现 6. 实现关系6.1图解6.2代码实现 在UML中&#xff0c;共有四种关系&#xff1…

php redis分布式锁

一&#xff0c;概念 在PHP中实现分布式锁通常可以使用数据库、缓存系统&#xff08;如Redis&#xff09;或者其他中央存储系统来保证在分布式系统中的数据一致性与同步。秒杀下单、抢红包等等业务场景&#xff0c;都需要用到分布式锁。 常规方案大概有七中 方案一&#xff1a;…