Java实现Base64的编码与解码

什么是Base64?

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

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

关于Base64我们要明白的最重要的一点就是,他是一中编码格式,而不是加密算法

Base64编码索引表:

Java实现Base64的编码与解码_第1张图片

 

为什么会有Base64这个东西出现?

Base64的出现是为了让一些二进制数据可视化并且能够进行传输,存储。例如图片、音频、视频等。

Base64 会经常用作一个简单的“加密”来保护某些数据,而真正的加密通常都比较繁琐。

规则:

Base64将3个字节变成4个字节。

如果要编码的字节数不能被3整除,最后会多出1个或2个字节,那么可以使用下面的方法进行处理:先使用0字节值在末尾补足,使其能够被3整除,然后再进行Base64的编码。在编码后的Base64文本后加上一个或两个=号,代表补足的字节数。也就是说,当最后剩余两个八位(待补足)字节(2个byte)时,最后一个6位的Base64字节块有四位是0值,最后附加上两个等号;如果最后剩余一个八位(待补足)字节(1个byte)时,最后一个6位的base字节块有两位是0值,最后附加一个等号。

下面我们用Java实现Base64算法:

首先我们要将Base64的对照表存进一个char型数组中去,为了之后要用的时候可以直接查表打印。

public static char[] base64 = {
        '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', '+', '/'
};

以下是编码的代码:


private static List encodeToBase64(byte[] bytes) {
​
    //记录编码的字节数被3除的余数
        int num = bytes.length % 3;
​
        List stringList = new ArrayList();
        int v = 0;
        for (int i = 2; i < bytes.length; i += 3) {
            //用V来接收拼接后的数,由于byte数组中每一个是8位的二进制数,三个拼起来正好是24位
            v = ((bytes[i - 2] & 0xff) << 16) | ((bytes[i - 1] & 0xff) << 8) | (bytes[i] & 0xff);
            //在将v与0x3f进行&运算,每次取到六位,将其分成4组
            //与0x3f进行&运算,是因为0x3f的二进制码是0011 1111,中间包含六个1,只有在全一的时候才会为1,所以值取到了最后六位
            int d0 = v & 0x3f;
            int d1 = v >>> 6 & 0x3f;//>>>为无符号的位运算
            int d2 = v >>> 12 & 0x3f;
            int d3 = v >>> 18 & 0x3f;
​
            //将取得的4组6位数据查表后存入List中
            stringList.add(String.valueOf(base64[d3]));
            stringList.add(String.valueOf(base64[d2]));
            stringList.add(String.valueOf(base64[d1]));
            stringList.add(String.valueOf(base64[d0]));
​
        }
    //下面的操作是当编码的字节数不能被3整除时,在末尾添加等于号
        if (num > 1) {
            v = ((bytes[bytes.length - 2] & 0xff) << 16) | ((bytes[bytes.length - 1] & 0xff) << 8);
​
            int d1 = v >>> 6 & 0x3f;
            int d2 = v >>> 12 & 0x3f;
            int d3 = v >>> 18 & 0x3f;
            stringList.add(String.valueOf(base64[d3]));
            stringList.add(String.valueOf(base64[d2]));
            stringList.add(String.valueOf(base64[d1]));
            stringList.add("=");
        }
        if (num == 1) {
            v = ((bytes[bytes.length - 1] & 0xff) << 16);
​
            int d2 = v >>> 12 & 0x3f;
            int d3 = v >>> 18 & 0x3f;
            stringList.add(String.valueOf(base64[d3]));
            stringList.add(String.valueOf(base64[d2]));
            stringList.add("=");
            stringList.add("=");
        }
    //输出编码后结果
        System.out.print("Base64 编码后:");
        for (String s : stringList) {
            System.out.print(s);
        }
        System.out.println();
        return stringList;
    }

相对编码来说,解码会更加简单些,代码如下:

private static void decode(String string) {
​
        byte[] b = new byte[string.length()];
        char[] ch = string.toCharArray();
        int n = 0;
    //遍历Base64表获取下标并存入byte数组
        for (char c : ch) {
            for (int i = 0; i < base64.length; i++) {
                if (c == base64[i]) {
                    b[n] = (byte) i;
                    n++;
                }
            }
        }
​
        int v = 0;
        byte[] bytes = new byte[string.length() - 1];
        int num = 0;
    //将4组合并,并且分为3组每组8位
        for (int i = 0; i < b.length; i += 4) {
            v = ((b[i] & 0xff) << 18) | ((b[i + 1] & 0xff) << 12) | (b[i + 2] & 0xff) << 6 | (b[i + 3] & 0xff);
​
            int d0 = v & 0xff;
            int d1 = v >>> 8 & 0xff;
            int d2 = v >>> 16 & 0xff;
​
            bytes[num] = (byte) d2;
            bytes[num + 1] = (byte) d1;
            bytes[num + 2] = (byte) d0;
            num += 3;
​
        }
//去除byte数组末尾的0,末尾有0才去除
        if (bytes[bytes.length - 1] == 0){
            try {
                int length = 0;
                for (int i = 0; i < bytes.length; ++i) {
                    if (bytes[i] == 0) {
                        length = i;
                        break;
                    }
                }
                String str1 = new String(bytes,0,length);
                System.out.println("字符串 "+string+" Base64 解码后:"+str1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
​
        String s1 = new String(bytes);
        System.out.println("字符串 "+string+" Base64 解码后:"+s1);
        }
    }

最后我们只要调用方法就好了。

测试用例:

原始字符串:丢

Base64 编码后:5Lii

再用 Base64 解码后:丢

原始字符串:丢15as

Base64 编码后:5LiiMTVhcw==

再用 Base64 解码后:丢15as

想了解更详细的介绍可以点击链接:Base64。

如果有不明白的地方也可以私信我哦~

你可能感兴趣的:(java,开发语言,后端,base64)