base64的概念和练习

base64概念

base64编码简单的说就是对字节流的一种编码。

base64的码表使用[A~Z] 、 [a~z] 、  [0-9] 、  +  、 / 一共64个字符组成,分别对应[0-63]的索引。

编码方法:将一个字符串按照某种字符集获得字节流后,将字节流每6位依次取出,6位bit最大值为63,正好对应base64的码表,不足6位时后面补0,根据6位bit对应的十进制数为索引找到base64码表中的编码。可以看出原始字节流3个字节,3*8bit = 24bit 等于 base64编码的4个编码 4*6bit=24bit 长度,当最后bit数不够产生4个base64编码时会用"="补在base64编码的后面。


用一个简单例子梳理一下流程,例如获得字符A的base64编码,A使用gbk字符集:

1. 获取A的字节流(byte数组)

A 对应ascii码65,对应二进制01000001

2. 按照base64格式每6个bit进行编码

01000001 对应 010000 010000

3. 将6个bit转成base64编码

010000对应十进制 16 ,对应base64编码 Q 

4. 不足4个编码以'='补充

最后结果 QQ==


MIME中的base64:

在邮件收发时邮件的主题、邮箱地址、附件名称等经常会用到base64和Quoted-printable等进行编码,在传输使用编码过的数据时会以=?[字符集]?[B/Q]?[具体base64编码]?= 来进行传输。

例如,如下邮件头信息中的 From、Subject信息是使用了base64编码

Received: from qiye.163.com (unknown [192.168.224.143])
	by mfast2 (Coremail) with SMTP id yOCowEBpbkJXrQ5ZnB8KAA--.714S2;
	Sun, 07 May 2017 13:15:03 +0800 (CST)
From: =?utf-8?B?5LyB5Lia6YKu566x?= <notice@qiye.163.com>
Reply-To: notice@qiye.163.com
To: xxxxx@xxx.xxx.com
Message-ID: <98944601.5.1494134105220.OfficialService-3.0.notice@qiye.163.com>
Subject: =?utf-8?B?W+S8geS4mumZkOaXtuemj+WIqV3msp/pgJrmiJDmnKzkuIA=?=
 =?utf-8?B?6ZmN5YaN6ZmNLOeUteivneS8muiuruWFheWAvOWKoOmAgSE=?=
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit
......

处理base64的工具

apache commons-codec 中提供的Base64工具 、 javax.mail 自带的编码解码工具MimeUtility。


下面是使用commons-codec和javax.mail的工具来编解码base64,和自己练习写的一个编解码base64工具的测试代码。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.mail.internet.MimeUtility;

import org.apache.commons.codec.binary.Base64;

public class CodeUtil {
    
    //base64 code
    public static Map<Integer, Character> base64Map=  new HashMap<Integer, Character>();
    static {
        int ascii_num_A =  65;
        for(int i=0 ;i<26 ; i++){
            base64Map.put(i , (char)ascii_num_A++);    
        }
        int ascii_num_a = 97;
        for(int i=26 ;i<52 ; i++){
            base64Map.put(i , (char)ascii_num_a++ );    
        }
        
        
        int ascii_num_0 = 48;
        for(int i=52 ;i<62 ; i++){
            base64Map.put(i , (char)ascii_num_0++ );    
        }
        
        base64Map.put(62, '+');
        base64Map.put(63, '/');
    }
    
    
    /**
     * 获取字符串对应的ascii码数组
     * @param s
     * @return int[]
     * @throws Exception
     */
    public static int[] getStringAscii(String s , String code) throws Exception{
        StringBuilder sb = new StringBuilder();
        byte[] bytes = s.getBytes(code);
        int[] asc2 = new int[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            sb.append(bytes[i] + " ");
            asc2[i] = bytes[i];
        }
        System.out.println(sb.toString());
        return asc2;
    }
    
    
    /**
     * 将asc2码转为二进制数组
     * @param asc2
     * @return
     * @throws Exception
     */
    public static String[] asciiToBinary(int[] asc2) throws Exception{
        String[] binary = new String[asc2.length];
        for(int i=0; i<asc2.length; i++){
            String b = Integer.toBinaryString(asc2[i] & 0xff);
            if(b.length() < 8){
                for(int j=0 , k=8-b.length(); j<k ; j++){
                    b = '0' + b;    
                }
                
            }
            binary[i] = b;
            System.out.print(b + " ");
        }
        System.out.println();
        return binary;
    }
    
    
    /**
     * 将二进制编码转为base64的格式
     * 6位一组
     * @param oriBinary
     * @return
     * @throws Exception
     */
    public static String[] getBase64Binary(String[] oriBinary) throws Exception{
        List<String> base64Binary = new ArrayList<String>(); 
        
        for(int i=0 , j = oriBinary.length; i<j ; i++){
            String oldBinary = oriBinary[i];
            
            if(base64Binary.size() == 0){
                base64Binary.add(oldBinary.substring(0, 6));
                base64Binary.add(oldBinary.substring(6));
            }else{
                String curBinary = base64Binary.get(base64Binary.size()-1);
                if(curBinary.length() < 6){
                    int l = 6 - curBinary.length();
                    curBinary += oldBinary.substring(0, l);
                    base64Binary.set(base64Binary.size()-1 , curBinary);
                    base64Binary.add(oldBinary.substring(l));
                }else{
                    base64Binary.add(oldBinary.substring(0, 6));
                    base64Binary.add(oldBinary.substring(6));
                }    
            }
            
        }
        if(base64Binary.size() > 0){
            String curBinary = base64Binary.get(base64Binary.size()-1);
            int l = 6 - curBinary.length();
            if(l > 0){
                for(int i=0; i<l ; i++){
                    curBinary += "0";
                }
                base64Binary.set(base64Binary.size()-1, curBinary);
            }
        }
        
        String[] a = new String[base64Binary.size()];
        return base64Binary.toArray(a);
    } 
        
    /**
     * 将字符串数组格式化为一个字符串,每个字符串间有一个空格
     * @param ss
     * @return
     * @throws Exception
     */
    public static String formateStringArray(String[] ss) throws Exception{
        StringBuilder sb = new StringBuilder();
        for(String s : ss){
            sb.append(s + " ");
        }
        return sb.toString();
    }    
        
    /**
     * 将输入的字符串按指定编码转为base64
     * @param str
     * @param charset
     * @return
     * @throws Exception
     */
    public static String encodeStrToBase64 (String str , String charset) throws Exception{
        StringBuffer sb = new StringBuffer();
        int[] asciis = getStringAscii(str, charset);
        String[] binarys = asciiToBinary(asciis);
        String[] base64Binary = getBase64Binary(binarys);
        String formateBase64Binary = formateStringArray(base64Binary);
        System.out.println(formateBase64Binary);
        for(int i=0; i<base64Binary.length ; i++){
            sb.append(base64Map.get(Integer.parseInt(base64Binary[i],2)));
        }
        int n = base64Binary.length % 4;
        for(int i=0; i<n; i++){
            sb.append("=");
        }        
        return sb.toString();
    }
    
    
    public static void commonsCodec (String str, String charset) throws Exception {
        System.out.println("\n\n********* 使用 org.apache.commons.codec.binary.Base64 工具进行 base64编码...");
        String base64 =  Base64.encodeBase64String(str.getBytes(charset));
        System.out.println("原始字符串:" + str + " \n编码后:" + base64);
        
        System.out.println("\n\n****************  使用 org.apache.commons.codec.binary.Base64 工具进行 base64解码...");
        byte[] bytes = Base64.decodeBase64(base64);
        String newStr = new String(bytes, charset);
        System.out.println("原始base64编码:" + base64 + "\n解码后:" + newStr);
    }
    
    public static void javamail(String str, String charset) throws Exception{
        System.out.println("\n\n ********** 使用 javax.mail.internet.MimeUtility 工具 进行base64编码...");
        String mimeBase64 = MimeUtility.encodeText(str ,charset , "B");
        System.out.println("原始字符串:" + str + " \n编码后:" + mimeBase64);
        
        System.out.println("\n\n ***************  使用javamail 的 javax.mail.internet.MimeUtility 工具 进行base64解码...");
        System.out.println("原始base64编码:" + mimeBase64 + "\n解码后:" + MimeUtility.decodeText(mimeBase64));

    }
    
    
    public static void main(String[] args)  throws Exception{
        String str = "张三";
        String charset = "gbk";
        System.out.println(encodeStrToBase64(str, charset));
        commonsCodec(str, charset);
        javamail(str, charset);
    }
}

结果:

-43 -59 -56 -3 
11010101 11000101 11001000 11111101 
110101 011100 010111 001000 111111 010000 
1cXI/Q==


********* 使用 org.apache.commons.codec.binary.Base64 工具进行 base64编码...
原始字符串:张三 
编码后:1cXI/Q==


****************  使用 org.apache.commons.codec.binary.Base64 工具进行 base64解码...
原始base64编码:1cXI/Q==
解码后:张三


 ********** 使用 javax.mail.internet.MimeUtility 工具 进行base64编码...
原始字符串:张三 
编码后:=?gbk?B?1cXI/Q==?=


 ***************  使用javamail 的 javax.mail.internet.MimeUtility 工具 进行base64解码...
原始base64编码:=?gbk?B?1cXI/Q==?=
解码后:张三







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值