一文搞懂base64编码

前言

Android开发中,base64编码还是比较常用的,用归用,其原理还是有必要理解的。

Android中使用base64编码:

private void base64Test() {
        String baseStr = "ab中国。";
        byte[] bytes = baseStr.getBytes();
        //默认编码
        System.out.println("DEFAULT   :" + ByteUtil.bytes2Str(Base64.encode(bytes, Base64.DEFAULT)));
        //末尾少填充符=
        System.out.println("NO_PADDING:" + ByteUtil.bytes2Str(Base64.encode(bytes, Base64.NO_PADDING)));
        //每组(76个字符一组)少了换行符\n
        System.out.println("NO_WRAP   :" + ByteUtil.bytes2Str(Base64.encode(bytes, Base64.NO_WRAP)));
       //Windows操作系统采用两个字符来进行换行,即CRLF
        System.out.println("CRLF      :" + ByteUtil.bytes2Str(Base64.encode(bytes, Base64.CRLF)));
        //编码字符的'+', '/'替换成了'-', '_'编码,适用于url编码
        System.out.println("URL_SAFE  :" + ByteUtil.bytes2Str(Base64.encode(bytes, Base64.URL_SAFE)));
        System.out.println("NO_CLOSE  :" + ByteUtil.bytes2Str(Base64.encode(bytes, Base64.NO_CLOSE)));
    }

注意:Unix/Linux/Mac OS X操作系统采用单个字符LF来进行换行

  • CR:Carriage Return,对应ASCII中转义字符\r,表示回车
  • LF:Linefeed,对应ASCII中转义字符\n,表示换行
  • CRLF:Carriage Return & Linefeed,\r\n,表示回车并换行

上述输出:

		 DEFAULT   :YWLkuK3lm73jgII=
         NO_PADDING:YWLkuK3lm73jgII
         NO_WRAP   :YWLkuK3lm73jgII=
         CRLF      :YWLkuK3lm73jgII=
         URL_SAFE  :YWLkuK3lm73jgII=
         NO_CLOSE  :YWLkuK3lm73jgII=

实际使用Base64.DEFAULT,Base64.NO_WRAP居多,上面五种编码规则是一样的,只不过输出的时候是为了适配不同业务场景。本次以Base64.NO_WRAP说明编码原理,理解字符ab中国。如何经过base64编码后输出YWLkuK3lm73jgII=

base64编码规则

  1. 把3个字节变成4个字节。
  2. 每76个字符加一个换行符。
  3. 最后的结束符也要处理。

简单就是说:
Base64编码使用了ASCII编码中64个可打印的字符(大写字母A-Z,小写字母a-z,数字0~9以及"+","/")将任意字节数据进行编码。Base64编码将串起来的二进制以6位进行分割.所以分切之前的二进制位数应该是24的倍数(即6,8的最小公倍数)。如果不足24位,则在编码后数据后面添加"=",一个"="想当于6个二进制位.数据量是原先的4/3倍。

上面分割的每6位二进制字符为一组,每一组转成是十进制值(码值),然后根据下面的Base64编码表的码值找到对应的字符(编码后的实际字符),最后将字符拼接起来就是最终的编码字符。

Base64编码表

 码值 字符
 0	A	   8	I	16	Q	24	Y	32	g	40	o	48	w	56	4
 1	B	   9	J	17	R	25	Z	33	h	41	p	49	x	57	5
 2	C	  10	K	18	S	26	a	34	i	42	q	50	y	58	6
 3	D	  11	L	19	T	27	b	35	j	43	r	51	z	59	7
 4	E	  12	M	20	U	28	c	36	k	44	s	52	0	60	8
 5	F	  13	N	21	V	29	d	37	l	45	t	53	1	61	9
 6	G	  14	O	22	W	30	e	38	m	46	u	54	2	62	+
 7	H     15	P	23	X	31	f	39	n	47	v	55	3	63	/

示例说明base64编码过程

上面说了其编码规则,下面通过demo理解其实现过程。看图:

在这里插入图片描述

对应的代码

  public static void main(String[] args) {
        byte[] strBytes = new byte[0];
        try {
            //UTF-8编码下一个汉字(包括中文形式下的符号)一般是3个字节,一个英文(包括英文下的符号)1个字节,一个数字1个字节
            //不同字符编码规则,base64输出结果也不同
            strBytes = "ab中国。".getBytes("UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(strBytes  == null){
       		 return;
        }
        //示例仅处理中英文,其它语言不处理
        //将字符字节数组,转成二进制字符串
        String s =  Base64TestUtils.byteArrToBinStr(strBytes);

        System.out.println(s);
        System.out.println();
        int length = s.length();

        for (int i = 0; i < length; i += 6) {
            int end;
            if (i + 6 > length) {
                end = length;
            } else {
                end = i + 6;
            }
            String substring = s.substring(i, end);
            //每6位一组
            if (substring.length() == 6) {
                System.out.println(substring + "," + Integer.parseInt(substring, 2));
            } else {
            	//不足6位,低位补0,凑够6位
                substring = Base64TestUtils.binaryFillZero(substring, 6,false);
                System.out.println(substring + "," + Integer.parseInt(substring, 2));
                //计算不需要补的等于号符号数,一个=等于6个二进制位
                int fillZeroNum = length % 24 == 0 ? 0 : 24 - length % 24;
                //等于号个数
                int equalCharNum = fillZeroNum % 6 == 0 ? 0 : fillZeroNum / 6;
                System.out.println("需要补等于号个数equalCharNum:" + equalCharNum);
            }

        }

    }
    /**
     * byte数组转换为二进制字符串
     **/
    public static String byteArrToBinStr(byte[] strBytes) {
        StringBuilder sb = new StringBuilder();
        for (byte c : strBytes) {
            String binary;
            if (c >= 0 && c < 128) {//ASCII码,取值范围是0~127
                binary = binaryFillZero(Integer.toBinaryString(c), 8);
            } else {//汉字之类
                //取低8位
                binary = Integer.toBinaryString(c & 0xff);
            }
            sb.append(binary);
        }
        return sb.toString();
    }

    public static String binaryFillZero(String binaryString, int bitNum) {
        return binaryFillZero(binaryString, bitNum, true);
    }

    /**
     * 对二进制位高位或低位补0
     *
     * @param binaryString 二进制字符串
     * @param bitNum     二进制位数
     * @param prefix       true前补0
     * @return
     */
    public static String binaryFillZero(String binaryString, int bitNum, boolean prefix) {
      /*  if (bitNum % 8 > 0) {
            throw new IllegalArgumentException("不支持的bitNum:" + bitNum);
        }*/
        StringBuffer sb = new StringBuffer();
        if (binaryString.length() < bitNum) {
            for (int i = 0; i < bitNum - binaryString.length(); i++) {
                sb.append(0);
            }
        }
        if (prefix) {//高位补0
            sb.append(binaryString);
        } else {//低位补0
            sb.insert(0,binaryString);
        }
        return sb.toString();
    }

小结

上面主要说了base64编码的原理,解码原理是其逆向过程。如有不足,请指出修正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值