Base64(基底64)是一种基于64个可打印字符来表示二进制数据的表示方法。每6个比特为一个单元,对应某个可打印字符。3个字节相当于24个比特,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。在Base64中的可打印字符包括字母A-Za-z、数子0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后BinHex的版本使用不同的64字符集来代表6个二进制数字,但是不被称为Base64。

Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括MIME的电子邮件及XML的一些复杂数据。

介绍完Base64之后,下面来看看我的实现代码:

编码的实现代码如下:

 /*** 编码方法* @param str 字符串* @return 返回编码后的字符串*/public static String toBase64(String str) {//把str按字符放入bytes数组byte[] bytes = str.getBytes(StandardCharsets.UTF_8);//记录需要补等号的个数int count = 3 - (bytes.length % 3);//记录数组长度int length = bytes.length;//下标指针int index = 0;//定义一个StringBuilder来存放编码后的字符串StringBuilder sb = new StringBuilder();while((length - index) >= 3) {//当数组长度比下标指针相差3甚至更多时,就将bytes[index],bytes[index + 1],bytes[index + 2]// (每一个bytes[]都由8位二进制数组成)拼接成24位二进制数int v = (bytes[index] & 0xFF) << 16 | (bytes[index + 1] & 0xFF) << 8 | (bytes[index + 2] & 0xFF);//每6位为一组转化成十进制数,然后把找到char[十进制数]对应的值放入StringBuilder//右移18位,取6位sb.append(toBase64[v >>> 18 & 0x3F]);//右移12位,取6位sb.append(toBase64[v >>> 12 & 0x3F]);//右移6位,取6位sb.append(toBase64[v >>> 6 & 0x3F]);//取6位sb.append(toBase64[v & 0x3F]);//下标指针加3index += 3;//如果还满足(length - index) >= 3,取接下来的3个bytes[]进行拼接,不满足则跳出循环}if (count == 1){//如果需要补1个等号//bytes[index],bytes[index + 1]拼接成16位二进制数int v = (bytes[index] & 0xFF) << 8 | (bytes[index + 1] & 0xFF);//每6位为一组转化成十进制数,然后把找到char[十进制数]对应的值放入StringBuilder//右移10位,取6位sb.append(toBase64[v >>> 10 & 0x3F]);//右移4位,取6位sb.append(toBase64[v >>> 4 & 0x3F]);//左移2位(相当于需要借2位),取6位sb.append(toBase64[v << 2 & 0x3F]);sb.append('=');}else if (count == 2){//如果需要补2个等号//bytes[index]化成8位二进制数int v = (bytes[index] & 0xFF);//每6位为一组转化成十进制数,然后把找到char[十进制数]对应的值放入StringBuilder//右移2位,取6位sb.append(toBase64[v >>> 2 & 0x3F]);//左移4位(相当于需要借4位),取6位sb.append(toBase64[v << 4 & 0x3F]);sb.append('=');sb.append('=');}return sb.toString();}

解码的实现代码如下:

/*** 解码方法* @param str 字符串* @return 返回解码后的字符串*/public static String reversalBase64(String str) {//记录=的数量int count = 0;//arr下标指针int index = 0;//bytes下标指针int indexs = 0;//遍历字符串得到=的数量for (int i = 0; i < str.length(); i++) {if (str.charAt(i) == '=') {count++;}}//new一个arr数组用来存放非=的字符串int length = str.length() - count;int[] arr = new int[length];//得到arr数组的值所对应的char数组的下标for (int i = 0; i < length; i++) {for (int j = 0; j < toBase64.length; j++) {if (str.charAt(i) == toBase64[j]) {arr[i] = j;}}}//new一个bytes数组用来存放解码后的字符串的每一个字符byte[] bytes = new byte[str.length() / 4 * 3 - count];while ((length / 4) > 0) {//当arr数组长度大于等于4时,就将arr[index],arr[index + 1],arr[index + 2],arr[index + 3]// (每一个arr[]都由6位二进制数组成)拼接成24位二进制数int v = (arr[index] & 0x3F) << 18 | (arr[index + 1] & 0x3F) << 12 | (arr[index + 2] & 0x3F) << 6 | (arr[index + 3] & 0x3F);//每8位为一组转化成byte型,并赋值给bytes//右移16位,取8位bytes[indexs] = (byte) (v >>> 16 & 0xFF);//右移8位,取8位bytes[indexs + 1] = (byte) (v >>> 8 & 0xFF);//取8位bytes[indexs + 2] = (byte) (v & 0xFF);//bytes下标指针加3indexs += 3;//arr下标指针加4index += 4;//arr数组长度减4length -= 4;//如果还满足(length / 4) > 0,取接下来的4个arr[]进行拼接,不满足则跳出循环}if (count == 1) {//如果存在1个=//将arr[index],arr[index + 1],arr[index + 2]拼接成18位二进制数int v = (arr[index] & 0x3F) << 12 | (arr[index + 1] & 0x3F) << 6 | (arr[index + 2] & 0x3F);//每8位为一组转化成byte型,并赋值给bytes//右移10位,取8位bytes[indexs] = (byte) (v >>> 10 & 0xFF);//右移2位,取8位bytes[indexs + 1] = (byte) (v >>> 2 & 0xFF);} else if (count == 2) {//如果存在2个=//将arr[index],arr[index + 1]拼接成12位二进制数int v = (arr[index] & 0x3F) << 6 | (arr[index + 1] & 0x3F);//每8位为一组转化成byte型,并赋值给bytes//右移4位,取8位bytes[indexs] = (byte) (v >>> 4 & 0xFF);}//将bytes数组中存的字符转换成String类型String result = new String(bytes, StandardCharsets.UTF_8);return result;}

总代码含测试代码和结果如下:

package practice;import java.nio.charset.StandardCharsets;public class Base64 {//用一个char数组封装base64码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', '+', '/'};public static void main(String[] args) {String str = "好好学习";System.out.println("编码前:"+str);str = toBase64(str);System.out.println("编码后:"+str);str = reversalBase64(str);System.out.println("解码后:"+str);}/*** 编码方法* @param str 字符串* @return 返回编码后的字符串*/public static String toBase64(String str) {//把str按字符放入bytes数组byte[] bytes = str.getBytes(StandardCharsets.UTF_8);//记录需要补等号的个数int count = 3 - (bytes.length % 3);//记录数组长度int length = bytes.length;//下标指针int index = 0;//定义一个StringBuilder来存放编码后的字符串StringBuilder sb = new StringBuilder();while((length - index) >= 3) {//当数组长度比下标指针相差3甚至更多时,就将bytes[index],bytes[index + 1],bytes[index + 2]// (每一个bytes[]都由8位二进制数组成)拼接成24位二进制数int v = (bytes[index] & 0xFF) << 16 | (bytes[index + 1] & 0xFF) << 8 | (bytes[index + 2] & 0xFF);//每6位为一组转化成十进制数,然后把找到char[十进制数]对应的值放入StringBuilder//右移18位,取6位sb.append(toBase64[v >>> 18 & 0x3F]);//右移12位,取6位sb.append(toBase64[v >>> 12 & 0x3F]);//右移6位,取6位sb.append(toBase64[v >>> 6 & 0x3F]);//取6位sb.append(toBase64[v & 0x3F]);//下标指针加3index += 3;//如果还满足(length - index) >= 3,取接下来的3个bytes[]进行拼接,不满足则跳出循环}if (count == 1){//如果需要补1个等号//bytes[index],bytes[index + 1]拼接成16位二进制数int v = (bytes[index] & 0xFF) << 8 | (bytes[index + 1] & 0xFF);//每6位为一组转化成十进制数,然后把找到char[十进制数]对应的值放入StringBuilder//右移10位,取6位sb.append(toBase64[v >>> 10 & 0x3F]);//右移4位,取6位sb.append(toBase64[v >>> 4 & 0x3F]);//左移2位(相当于需要借2位),取6位sb.append(toBase64[v << 2 & 0x3F]);sb.append('=');}else if (count == 2){//如果需要补2个等号//bytes[index]化成8位二进制数int v = (bytes[index] & 0xFF);//每6位为一组转化成十进制数,然后把找到char[十进制数]对应的值放入StringBuilder//右移2位,取6位sb.append(toBase64[v >>> 2 & 0x3F]);//左移4位(相当于需要借4位),取6位sb.append(toBase64[v << 4 & 0x3F]);sb.append('=');sb.append('=');}return sb.toString();}/*** 解码方法* @param str 字符串* @return 返回解码后的字符串*/public static String reversalBase64(String str) {//记录=的数量int count = 0;//arr下标指针int index = 0;//bytes下标指针int indexs = 0;//遍历字符串得到=的数量for (int i = 0; i < str.length(); i++) {if (str.charAt(i) == '=') {count++;}}//new一个arr数组用来存放非=的字符串int length = str.length() - count;int[] arr = new int[length];//得到arr数组的值所对应的char数组的下标for (int i = 0; i < length; i++) {for (int j = 0; j < toBase64.length; j++) {if (str.charAt(i) == toBase64[j]) {arr[i] = j;}}}//new一个bytes数组用来存放解码后的字符串的每一个字符byte[] bytes = new byte[str.length() / 4 * 3 - count];while ((length / 4) > 0) {//当arr数组长度大于等于4时,就将arr[index],arr[index + 1],arr[index + 2],arr[index + 3]// (每一个arr[]都由6位二进制数组成)拼接成24位二进制数int v = (arr[index] & 0x3F) << 18 | (arr[index + 1] & 0x3F) << 12 | (arr[index + 2] & 0x3F) << 6 | (arr[index + 3] & 0x3F);//每8位为一组转化成byte型,并赋值给bytes//右移16位,取8位bytes[indexs] = (byte) (v >>> 16 & 0xFF);//右移8位,取8位bytes[indexs + 1] = (byte) (v >>> 8 & 0xFF);//取8位bytes[indexs + 2] = (byte) (v & 0xFF);//bytes下标指针加3indexs += 3;//arr下标指针加4index += 4;//arr数组长度减4length -= 4;//如果还满足(length / 4) > 0,取接下来的4个arr[]进行拼接,不满足则跳出循环}if (count == 1) {//如果存在1个=//将arr[index],arr[index + 1],arr[index + 2]拼接成18位二进制数int v = (arr[index] & 0x3F) << 12 | (arr[index + 1] & 0x3F) << 6 | (arr[index + 2] & 0x3F);//每8位为一组转化成byte型,并赋值给bytes//右移10位,取8位bytes[indexs] = (byte) (v >>> 10 & 0xFF);//右移2位,取8位bytes[indexs + 1] = (byte) (v >>> 2 & 0xFF);} else if (count == 2) {//如果存在2个=//将arr[index],arr[index + 1]拼接成12位二进制数int v = (arr[index] & 0x3F) << 6 | (arr[index + 1] & 0x3F);//每8位为一组转化成byte型,并赋值给bytes//右移4位,取8位bytes[indexs] = (byte) (v >>> 4 & 0xFF);}//将bytes数组中存的字符转换成String类型String result = new String(bytes, StandardCharsets.UTF_8);return result;}}

如果你有哪里看不懂的请在评论区与我交流 ,或者你有更好的见解也可以与我交流。

Base64的编码与解码的实现方法(超详细,每一行代码都含注释)相关推荐

  1. 彻底弄懂base64的编码与解码原理

    作者介绍 背景 base64的编码原理网上讲解较多,但解码原理讲解较少,并且没有对其中的内部实现原理进行剖析.想要彻底了解base64的编码与解码原理,请耐心看完此文,你一定会有所收获. 涉及算法与逻 ...

  2. img图片的预览和下载(iframe基本使用),图片转file格式,file文件转base64格式,base64的编码和解码

    目录 一.根据后端接口返回的URL下载和预览图片 1.调用下载图片函数实现下载图片 2.弹出另一个页面,实现预览图片. 3.不弹出另一个页面,实现下载/预览图片(iframe方式) 4.动态创建ifr ...

  3. php base64解码,PHP Base64 中英文编码 JavaScript 解码

    最新PHP Base64 中英文编码 JavaScript 解码 以下是三零网为大家整理的最新PHP Base64 中英文编码 JavaScript 解码的文章,希望大家能够喜欢! function ...

  4. javascript中的Base64.UTF8编码与解码详解

    javascript中的Base64.UTF8编码与解码详解 本文给大家介绍的是javascript中的Base64.UTF8编码与解码的函数源码分享以及使用范例,十分实用,推荐给小伙伴们,希望大家能 ...

  5. python怎么返回上一行代码_Python实现判断一行代码是否为注释的方法

    目前的编辑器大都可以自动检测某一行代码是否为代码行或注释行,但并不太提供代码行/注释行行数的统计,对于大量代码文件的代码行/注释行统计,就更少见一些.本篇文章试用一段Python脚本来实现这一目标,并 ...

  6. atob()和btoa() 进行base64的编码和解码

    编码: 解码:

  7. C语言 链表逆置四种方法 超详细

    链表逆置 C语言 创建所需的相关结构体 struct List {int date;struct List* next; }; 首先我们创建一个函数用于创建链表的. 建立创建链表的函数 struct ...

  8. js中使用btoa和atob进行Base64的编码和解码

    window.atob(string):解码 用来解码一个已经被base-64编码过的字符串.(参数string: 必需是一个通过 btoa() 方法编码的字符串) window.btoa(strin ...

  9. C# Base64图片编码和解码

    Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法.可查看RFC2045-RFC2049,上面有MIME的详细规范. Ba ...

  10. C++ 使用base64进行编码和解码

    1.base64编码的作用: base64编码的东西,任何人都可以解码,所以称之为加密和解密是不合适的,其作用是:便于数据再网络上的传输.举个简单的例子,你使用SMTP协议 (Simple Mail ...

最新文章

  1. 联手IBM布局云计算,王健林如何再造一个新万达?
  2. 2017年10月07日普及组 单元格
  3. Linux的追逐,Windows的穷途恼指日可待
  4. Taro+react开发(88):taro条件渲染
  5. Android支付宝刷步数,支付宝运动怎么刷步数? 支付宝如何快速刷步数?
  6. Vue_理解组件化开发
  7. 遗传算法(geatpy)
  8. Oracle CDB PDB基础知识
  9. 关于:什么是土地用途管制?针对村庄用地的各个地类每一个用地的用途管制的规则?针对土地用地调整怎么进行申报?
  10. 入驻商家卖违禁药物、评论造假、试水会员,直播能让新氧再次“乘风破浪”吗?
  11. 2019天津市二级计算机考试,天津市2019年9月计算机等级考试都有哪些考点可以报名?...
  12. web页面播放实时视频流
  13. echarts结合阿里云地图json选择器展示地图
  14. Vinted运营干货分享:Vinted国内使用详细步骤参考
  15. 程序员趣味儿逻辑测题-2(附答案)这次的题稍难,快来挑战吧!
  16. 面对海量IoT设备,如何打造高性能物联网平台接入层?
  17. 【BitLocker】解锁后快速上锁(不重启电脑)
  18. 常见的计算机网络教学模式有哪几种,常见的教学方法有哪几种
  19. Win7安装VS2008 SP1卡在 VS90sp1-KB945140-X86-CHS 的解决方法
  20. Win10 休眠按钮调不出来

热门文章

  1. 注册smtp服务器,SMTP授权码介绍及获取教程
  2. 【公司邮箱怎么注册】Foxmail帐户邮箱数据保存在什么地方?如何备份一个帐户?
  3. python文件夹排序笔记
  4. 小红书后台开发岗面试经历复盘
  5. python太极代码_旋转的太极图动画源代码
  6. 项目开发过程中业务流程图的绘制
  7. MySQL学习笔记①_案例记录
  8. html5 css 插入视频,HTML+CSS入门 HTML网页中插入视频各种方法
  9. 智能电视或将掀起IT产业新一轮狂潮
  10. Java使用while循环计算调和数列的和并打印