0
点赞
收藏
分享

微信扫一扫

【无标题】Base64编码和解码

九点韶留学 2022-01-10 阅读 69
java

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的一些复杂数据。

举例来说,一段引用自托马斯·霍布斯《利维坦》的文句:

Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.

经过Base64编码之后变成:

TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=

编码“Man”的结果为TWFu,详细原理如下:

文本Man
ASCII编码7797110
二进制位010011010110000101101110
索引1922546
Base64编码TWFu

简单来说Base64就是将一个字符串转换成二进制然后将8位分割成6位,再找到Base64索引表中对应的字符,如果要编码的字节数不能被三整除,那么在末尾补上0,最后转换成Base64时以=表示。参考下表:

文本(1 Byte)A
二进制位010000010000000000000000
二进制位(补0)010000010000000000000000
Base64编码QQ==
文本(2 Byte)BC
二进制位010000100100001100000000
二进制位(补0)010000100100001100000000
Base64编码QkM=

那么我们来用代码实现一下Base64的编码和解码:

首先根据上面的原理我们知道Base64的编码会需要一个对应表和二进制和十进制的相互转换。

先将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', '+', '/'
    };

然后写二进制和十进制转换的方法。这里我们写一个二进制转换成十进制的方法,而十进制转二进制我们用Intgrer对象的方法来实现。

public static int BinaryToDecimal(int binaryNumber) {
        //二进制转十进制
        int decimal = 0;
        int p = 0;
        while (true) {
            if (binaryNumber == 0) {
                break;
            } else {
                int temp = binaryNumber % 10;
                decimal += temp * Math.pow(2, p);
                binaryNumber = binaryNumber / 10;
                p++;
            }
        }
        return decimal;
    }

 我们先将一个字符串传过来,然后将它变成一个字节数组,注意因为中文的问题,这里转换成字符数组会出现问题,所以我们使用字节数组,然后对其进行判断,是不是3的倍数,需要补几个0,补完之后转换成二进制,转换成二进制之后再按每6位数得到一个新的二位数,根据这个新的二位数的十进制值去找到Base64对应表数组里对应的值,最后根据补0的数在编码后补上=,就完成了一个字符串的Base64编码。

 //base64编码
    public static String geyBase64(String str) throws UnsupportedEncodingException {
        if (str.getBytes().length % 3 == 1) {
            str = str + "00";
            byte[] b = str.getBytes();
            b[b.length - 1] = 0;
            b[b.length - 2] = 0;
            String result = "";
            for (int i = 0; i < b.length; i++) {
                result += Integer.toBinaryString((b[i] & 0xFF) + 0x100).substring(1);
            }
            String str1 = "";
            for (int i = 0; i < result.length() - 12; i = i + 6) {
                str1 += String.valueOf(toBase64[BinaryToDecimal(Integer.parseInt(result.substring(i, i + 6)))]);
            }
            str1 = str1 + "==";
            return str1;
        } else if (str.getBytes().length % 3 == 2) {
            str = str + "0";
            byte[] b = str.getBytes();
            b[b.length - 1] = 0;
            String result = "";
            for (int i = 0; i < b.length; i++) {
                result += Integer.toBinaryString((b[i] & 0xFF) + 0x100).substring(1);
            }
            String str1 = "";
            for (int i = 0; i < result.length() - 6; i = i + 6) {
                str1 += String.valueOf(toBase64[BinaryToDecimal(Integer.parseInt(result.substring(i, i + 6)))]);
            }
            str1 = str1 + "=";
            return str1;
        } else if (str.getBytes().length % 3 == 0) {
            byte[] b = str.getBytes();
            String result = "";
            for (int i = 0; i < b.length; i++) {
                result += Integer.toBinaryString((b[i] & 0xFF) + 0x100).substring(1);
            }
            String str1 = "";
            for (int i = 0; i < result.length(); i = i + 6) {
                str1 += String.valueOf(toBase64[BinaryToDecimal(Integer.parseInt(result.substring(i, i + 6)))]);
            }
            return str1;
        }

        return "0";
    }

而解码的过程就是上面的逆向操作。根据字符找到对应表数组的下标,将下标转换成二进制,再将6位的二进制重新取到8位,将其重新转换回字节数组,然后转成字符串。

 public static String getBase64String(String base) throws UnsupportedEncodingException {
        String result = "";
        base=base.replace('=','A');
        for (int i = 0; i < base.length(); i++) {
                    for (int j = 0; j < toBase64.length - 1; j++) {
                        if (base.charAt(i) == toBase64[j]) {
                            result += Integer.toBinaryString((j & 0xFF) + 0x100).substring(3);
                        }
                    }

            }
        byte[] b= new byte[result.length()/8];
        for (int k = 0; k < result.length(); k = k + 8) {
            b[k/8]=(byte) BinaryToDecimal(Integer.parseInt(result.substring(k, k + 8)));
        }
        String str = new String(b);
        return str;
    }

测试一下结果

public static void main(String[] args) throws UnsupportedEncodingException {
        String str = "今天是个好日子";
        String str2 = geyBase64(str);
        System.out.println(str2);
        String str3 =getBase64String(str2);
        System.out.println(str3);
    }

可以看到我们的程序编码之后和网站上的结果是一样的。解码也成功得到了原来的字符串。

 

 

举报

相关推荐

0 条评论