一.Base64編碼原理Base64是網絡上最常見的用於傳輸8Bit字節碼的編碼方式之一,其編碼原理如下:
1. 統計需要編輯的字符串長度,把需要編譯的字符串按每3個爲一組,長度整除3的在字符串後面加0補全,最終把字符串分爲若干組
2. 編碼時以組爲單位,組中的字符串轉爲ASCII編碼,得到3個ASCII編碼數字,再把3個ASCII編碼數字轉爲8bit字節的二進制,一共得到24個字節
3. 再把24個字節分爲4組,每組爲6bit字節的二進制,把每一組的二進制轉爲十進制
4. 根據Base64編碼表對數據進行編碼,得到Base64編碼。Base64編碼表如下
Base64 編碼表 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
Value | Char | Value | Char | Value | Char | Value | Char | |||
0 | A | 16 | Q | 32 | g | 48 | w | |||
1 | B | 17 | R | 33 | h | 49 | x | |||
2 | C | 18 | S | 34 | i | 50 | y | |||
3 | D | 19 | T | 35 | j | 51 | z | |||
4 | E | 20 | U | 36 | k | 52 | 0 | |||
5 | F | 21 | V | 37 | l | 53 | 1 | |||
6 | G | 22 | W | 38 | m | 54 | 2 | |||
7 | H | 23 | X | 39 | n | 55 | 3 | |||
8 | I | 24 | Y | 40 | o | 56 | 4 | |||
9 | J | 25 | Z | 41 | p | 57 | 5 | |||
10 | K | 26 | a | 42 | q | 58 | 6 | |||
11 | L | 27 | b | 43 | r | 59 | 7 | |||
12 | M | 28 | c | 44 | s | 60 | 8 | |||
13 | N | 29 | d | 45 | t | 61 | 9 | |||
14 | O | 30 | e | 46 | u | 62 | + | |||
15 | P | 31 | f | 47 | v | 63 | / |
Base64編碼舉例:
a)字符串(bat),長度爲3,能夠被3整除,base64編碼後結果爲:YmF0;其編碼過程如下:
原始字符 | b | a | t | |
ASCII: | 62 | 61 | 74 | |
8bit字節: | 01100010 | 01100001 | 01110100 | |
6bit字節: | 011000 | 100110 | 000101 | 110100 |
十進制: | 24 | 38 | 5 | 52 |
對應編碼: | Y | m | F | 0 |
b)字符串(eakom),長度爲5,不能被3整除,編碼是需要在後面補0,base64編碼後結果爲:ZWFrb20=;其編碼過程如下:
原始字符 | e | a | k | o | m | |||
ASCII: | 101 | 97 | 107 | 111 | 109 | |||
8bit字節: | 1100101 | 01100001 | 01101011 | 01101111 | 01101101 | 00000000 | ||
6bit字節: | 11001 | 010110 | 000101 | 101011 | 011011 | 110110 | 110100 | 000000 |
十進制: | 25 | 22 | 5 | 43 | 27 | 54 | 52 | 0 |
對應編碼: | Z | W | F | r | b | 2 | 0 | = |
編碼說明:把3個8位字節(3*8=24)轉化爲4個6位的字節(4*6=24),之後在6位的前面補兩個0,形成8位一個字節的形式。 如果剩下的字符不足3個字節,則用0填充,輸出字符使用'=',因此編碼後輸出的文本末尾可能會出現1或2個'='。
二、base64運用場景
a)用於URL中,迅雷下載和百度雲盤分析的URL鏈接大部分使用Base64編譯
b)嵌入Css文件中直接顯示圖片
#fkbx-spch, #fkbx-hspch {
background: url(data:image/gif;base64,R0lGODlhHAAmAKIHAKqqqsvLy0hISObm5vf394uLiwAAAP///yH5B…EoqQqJKAIBaQOVKHAXr3t7txgBjboSvB8EpLoFZywOAo3LFE5lYs/QW9LT1TRk1V7S2xYJADs=) no-repeat center;
}
c)HTML中嵌入base64編碼,瀏覽器解析Base64編碼顯示圖片
<img src="data:image/gif;base64,R0lGODlhHAAmAKIHAKqqqsvLy0hISObm5vf394uLiwAAAP///yH5B…EoqQqJKAIBaQOVKHAXr3t7txgBjboSvB8EpLoFZywOAo3LFE5lYs/QW9LT1TRk1V7S2xYJADs=">
三、Java常用的Base64編碼轉換
package com.eakom.common.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.bouncycastle.util.encoders.UrlBase64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* Base二進制文件處理類
* @author eakom
* @date 2017年5月26日
*/
public class Base64Utils {
private Base64Utils(){
}
private static final Logger logger=LoggerFactory.getLogger(Base64Utils.class );
public final static String ENCODING="UTF-8";
/**
* base64轉字符串
*
* @param str
* @return
* @throws UnsupportedEncodingException
*/
public static String Base642String(String str) throws UnsupportedEncodingException {
byte[] bytes = Base64.decodeBase64(str.getBytes());
return new String(bytes);
}
/**
* 字符串轉base64編碼
*
* @param str
* @return
* @throws UnsupportedEncodingException
*/
public static String String2Base64(String str) throws UnsupportedEncodingException {
byte[] bytes = Base64.encodeBase64(str.getBytes());
return new String(bytes);
}
/**
* 將string類型的數據轉碼爲byte類型.
*
* @param fileData
* String 類型的數據.
* @return 轉碼後的數據byte類型,發生異常或者filedate爲null或者“”時返回空byte[0].
*/
public static byte[] String2byte(String fileData) {
if (fileData != null&&!"".equals(fileData)) {
BASE64Decoder decoder = new BASE64Decoder();
try {
return decoder.decodeBuffer(fileData);
} catch (IOException e) {
logger.error("String2byte出錯", e);
}
}
return new byte[0];
}
/**
* 將byte類型的數據經過base64編碼轉爲string.
* @param fileData
* byte類型的數據 .
* @return 轉碼後的數據,發生異常或者filedate爲null時返回空"".
*/
public static String byte2String(byte[] fileData) {
if (fileData != null) {
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(fileData).replaceAll("\\s*","");
}
return "";
}
/**
* 將對象編碼爲base64的String.
*
* @param object
* 要進行編碼的對象.
* @return 編碼後的對象對應的bease64String.
*/
public static String Object2Base64(Object object) {
String objectString = null;
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(
arrayOutputStream);
objectOutputStream.writeObject(object);
objectString = byte2String(arrayOutputStream
.toByteArray());
} catch (IOException e) {
logger.error("Object2Base64出錯", e);
}
return objectString;
}
/**
* 將bease64的String解編碼爲對象;
*
* @param objectString
* 可以解編碼爲Object的Base64String,如果不能解編碼爲Object拋出異常.
* @return 解編碼成功後的對象.
*/
public static Object Base642Object(String objectString) {
Object object = null;
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
String2byte(objectString));
try {
ObjectInputStream objectInputStream = new ObjectInputStream(
byteArrayInputStream);
object = objectInputStream.readObject();
} catch (IOException e) {
logger.error("Base642Object", e);
} catch (ClassNotFoundException e) {
logger.error("Object2Base64路徑錯誤出錯", e);
}
return object;
}
/**
* 將InputStream類型的數據轉碼爲String.
*
* @param fileData
* InputStream類型的數據.
* @return 轉碼後的數據String類型,發生異常或者filedate爲null時返回null.
*/
public static String InputStream2String(InputStream fileData) {
if (fileData == null) {
return null;
}
BASE64Encoder encoder = new BASE64Encoder();
byte[] _fileData;
try {
_fileData = new byte[fileData.available()];
fileData.read(_fileData);
fileData.close();
return encoder.encode(_fileData).replaceAll("\\s*","");
} catch (IOException e) {
logger.error("InputStream2String出錯", e);
}
return null;
}
/**
* Base64轉InputStream
* @param data
* @return
*/
public static InputStream Base642InputStream(String base64){
BASE64Decoder decoder = new BASE64Decoder();
InputStream is=null;
try {
// 解密
byte[] b = decoder.decodeBuffer(base64);
// 處理數據
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {
b[i] += 256;
}
}
is = new ByteArrayInputStream(b);
}catch(IOException e){
logger.error("Base642InputStream", e);
}
return is;
}
/**
* 加密
* @param data
* @return
* @throws UnsupportedEncodingException
*/
public static String encoded(String data) throws UnsupportedEncodingException{
byte[] b=UrlBase64.encode(data.getBytes(ENCODING));
return new String(b,ENCODING);
}
/**
* 解密
* @param data
* @return
* @throws UnsupportedEncodingException
*/
public static String decode(String data) throws UnsupportedEncodingException{
byte[] b=UrlBase64.decode(data.getBytes(ENCODING));
return new String(b,ENCODING);
}
/**
* @Description: 將base64編碼字符串轉換爲圖片
* @Author:
* @CreateTime:
* @param imgStr base64編碼字符串
* @param path 圖片路徑-具體到文件
* @return
*/
public static boolean Base642Image(String imgStr, String path) {
if (imgStr == null){
return false;
}
BASE64Decoder decoder = new BASE64Decoder();
try {
// 解密
byte[] b = decoder.decodeBuffer(imgStr);
// 處理數據
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {
b[i] += 256;
}
}
OutputStream out = new FileOutputStream(path);
out.write(b);
out.flush();
out.close();
return true;
} catch (Exception e) {
logger.error("Base642Image異常", e);
return false;
}
}
/**
* @Description: 根據圖片地址轉換爲base64編碼字符串
* @Author:
* @CreateTime:
* @return
*/
public static String Image2Base64(String imgFile) {
InputStream inputStream = null;
byte[] data = null;
try {
inputStream = new FileInputStream(imgFile);
data = new byte[inputStream.available()];
inputStream.read(data);
inputStream.close();
} catch (IOException e) {
logger.error("Image2Base64出錯", e);
}
// 加密
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
public static void main(String[] args) throws UnsupportedEncodingException {
String image2String = Image2Base64("D:/二維碼-1497779927202.png");
String imgStr="/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAeAGQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3Gdb+BcwXEDoAS7XIwV/FcDH4VVsr28uJ3hRshSQZWQSJ07MpUenGM/00ZJ5EcqtpNIB/EpTB/NgaiWO11KHzJrMgkFCJotrgf5ParT01RLWuhYiM/ImWMY6MjH5vfBHH0yapXOmwuNken2jIRyS3lnP4Kf51z1yfFdv4tttMtdb0xbW5t7m6jWbTZJDGsbxKEZvPBYnzs7uPu9MHA7KpvZ6DtfcpRLfxZBWN17B5ydv47Mn8c05r2SN1SSyuMnOWQBlGOp4Ocfhk+meK4W81vx/d6reDw9/wjj6XFM8FvJfw3PnSmPCSkiPI4lDp0GduQMEE6ngfxBqOreHV1XxEdLivJiWt0si8Ye3IBjYiQ5y2Sw9Awzg7hT36C+Z1vmM8G+FMseiyZTv3yMj8qi+1Mn+utpk7blG8E+23Jx7kCuIkvdce11PVbh9J0+0tJrl3M2jSPLFBHI4WRiLhXJKKHyEBOeAeK6Hwvc3U+iW91qqyQ3skbSSK8c0SohYlQySM21wu3cNxw24Akc0WQXNeG8hlhVzLENzbOJAwLegPf+ftVWS1Vbgn7PdSgDCsHTI78OSH9e/c9q5Ea1rOtaxq0Gna5p9lptjcLZZvLIzyTybAztt3R7Y/nVQRu3YLZ24rp/DSazBY3FtrcdqJ4Ll0hmtQFjniwGVwnWM8lSpJ5UkEginsG5M8V95b+RvRCPlWWUMy85z05PBwC+OeeOKmgnu0iCz200jj+JRGufqN55qUXkMoYW8sU7gZ2JIMkd/8/wAqbLaWt/GGntgSRj51wwwemR7+hxRfuFuwv2mX/nxuP++o/wD4qiqot9Lsy0InEBByUF0y8/TdRRZdguy5cgBN7XTW6L1YbQPx3A1E1mLiHJvJ2yAUlRlUgexUDg8evQVYuHWO2lkfdsVCW2nBwB296xrG3t70S3dqMgvjbPGNwbHJDj5genPJzk8k0R2Bmfe2twPHOj2+6GdTpd8B56lsL51oSTydx/IV1SyKGETSIZtu4qOCR649M1xGq6RosWvmaUau8yhlaRdYu0ZA5VmCYlwFOF+UADKj0GOpsNZt9RnaGFJVYLuy4AGMgdj70NO1wTV7GD40vZJILLRnt/3eo30cMj+YVRokDTujEgAiRIjGRkjDtnOMHXjmu5HjS2jul+6x81laLb1OHwS2enXv7Yq5daVY3t/Y39xbRyXdg7vazH70RdCjYPoVPI6cA9QCLbAspAYqSMZHUfnSUl2Cxx+rC48S+Ik0G6s4JNCs0F1qny+ck8oIaG37EEECVl2nIEYPEmDq3Os6dfXM9hBeWDXdrtaa3ulOY9wyu4HG0kEkZHIrOi+HmkQyXMkFzq1o9zcPczGz1S5hEsj4y7KJMbjjqAPpxWg+kxaVaCKwtYmDShmmuppJZWdiF3F2JckAIAxbICgDgCnG1wexxn2Lwj4pnu7+0mvNF1JJprSe+0q4aKb5JApVivXPlqQGUgIRwCRjU8Ca9eBdT0fWNS/tK80+5CC88homnV443Hy8qSC7DCnOFUlctzWurPRb++W8msry3uWZWuJrLUJYGnKgBS5UgttGQuTwCQCM10emT6PYWcdtp2n+VHdTlZAVGZXO0M8jEkuxBGWbJbHJ71co26Exl5m8kqXETGKT/ZJXqp9wehHoaq3cUMSh/Kd5yAPMQOrNjH3mjGfw6cVL9kK8Q3EkMfaONUCj6ZWnyyG3hQnLnciZPBOWC54+uazW+hfqZsms3SuVj02SXH3im/g+hyg5xg/jRWuFVSxAALHJIHU9P6UU+aPYVn3P/9k=";
String path="D:/1234125.jpg";
Base642Image(imgStr, path);
System.out.println(image2String);
}
}
四、base64編碼後文件大小比之前的文件大了1/4,不利於保存;嵌入css中的base64編碼圖片會增加瀏覽器渲染的壓力,因此只適合嵌入一些小圖片,不適合把大圖片嵌入其中。Base64主要在一些特殊情況下處理圖片或PDF文件,其他地方慎重使用。
Base64 編碼表 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
Value | Char | Value | Char | Value | Char | Value | Char | |||
0 | A | 16 | Q | 32 | g | 48 | w | |||
1 | B | 17 | R | 33 | h | 49 | x | |||
2 | C | 18 | S | 34 | i | 50 | y | |||
3 | D | 19 | T | 35 | j | 51 | z | |||
4 | E | 20 | U | 36 | k | 52 | 0 | |||
5 | F | 21 | V | 37 | l | 53 | 1 | |||
6 | G | 22 | W | 38 | m | 54 | 2 | |||
7 | H | 23 | X | 39 | n | 55 | 3 | |||
8 | I | 24 | Y | 40 | o | 56 | 4 | |||
9 | J | 25 | Z | 41 | p | 57 | 5 | |||
10 | K | 26 | a | 42 | q | 58 | 6 | |||
11 | L | 27 | b | 43 | r | 59 | 7 | |||
12 | M | 28 | c | 44 | s | 60 | 8 | |||
13 | N | 29 | d | 45 | t | 61 | 9 | |||
14 | O | 30 | e | 46 | u | 62 | + | |||
15 | P | 31 | f | 47 | v | 63 | / |