Base64是一種基於64個可打印字符來表示二進制數據的表示方法。因爲{\displaystyle \log _{2}64=6}{\displaystyle \log _{2}64=6},因此每6個比特爲一個單元,對應某個可打印字符。3個字節至關於24個比特,對應於4個Base64單元,即3個字節可由4個可打印字符來表示。它可用來做爲電子郵件的傳輸編碼
編碼
一開始先要算一下一共多少位,好比對 qwer 進行編碼php
按照每 3 字節轉爲 4 個的規則,len(qwer) mod 3 = 1 也就是說多出來 1 字節,那咱們要補充 2 字節進去才能湊夠 3 字節web
放在 C 語言裏能夠這麼寫,其中 src 是待編碼的數據微信
char table[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//定義的字典,根據這個找具體在哪裏
fill_bit=((3-strlen(src)%3)%3);
for(int k=0;k<fill_bit;k++){
src[data_length+k]='0';
}
而後就到了編碼部分了,在此以前還要先介紹一下位操做編輯器
每一個字節有 8 bit,好比 q 就是 01110001,按位與操做 & 作的就是相同爲 1 不一樣爲 0ui
那 q 與 3 進行與運算就是(01110001 & 0011)= 1編碼
左移、右移在下文中就理解爲是把它直接移動就行了,好比 q 右移 2 位:就是 011100 01 的後兩位給移動出去,只剩下前 6 位,而後前面補上兩個 0url
int j=0;
for(int i=0;i<data_length;i+=3){
index=src[i]>>2;
result[j++]=table[index];
index=((src[i]&3)<<4)+(src[i+1]>>4);
result[j++]=table[index];
index=((src[i+1]&15)<<2)+(src[i+2]>>6);
result[j++]=table[index];
index=(src[i+2]&63);
result[j++]=table[index];
//<< >> 運算符的優先級低於+ -,注意加括號
}
index=src[i]>>2
是把第一個 'q' 向右移了 2 位,也就是取前 6 位,獲得了 00011100 也就是 28spa
result[j++]=table[index]
而後在字典中找第幾位,做爲結果,在字典中第 28 個是 c,因此就有了編碼後的第一個字符 'c'.net
src[i]&3
做用是取第一個 'q' 的後兩位 01,而後 (src[i]&3)<<4
左移4位 010000,再加第二個 'w' src[i+1]>>4
右移 4 位獲得的前 4 位 0111,加起來是 010111 也就是 23,在字典中第 23 位是 'X',獲得編碼後第二個字符3d
src[i+1]&15
是取第二個 'w' 後四位 0111(15 是 1111),左移 2 位得 00011100。第三個 'e' 右移 6 位 src[i+2]>>6
獲得的前 2 位 01,加起來獲得獲得 00011101 = 29 在字典中第 29 位是 'd'
最後再直接取第三個 'e' 的後 6 位 src[i+2]&63
(63 是 111111)
這樣一個循環就結束了,把三個變成了四個
下一個循環中算上前面補充的兩個 0 是這樣分的:
011100 100000 000000 000000
而後把補充的字符替換爲 '='
result_length=strlen(result);
for(int k=0;k<fill_bit;k++){
result[result_length-1-k]=padding_char;
}
cXdlcg==
解碼
int findchr(char *array,char ch){
for(int i=0;i<strlen(array);i++){
if(array[i]==ch){
return i;
}
}
return 0;
}
對於前面編碼的每個字符,都要從 table 表裏面去找對應的字符,好比 'A' 應該是 0
首先能夠把前面的 = 換成 A,由於 A 在咱們定義的字典中是 000000,跟前面補上的 0 是同樣的
for(int i=0;i<base_len;i++){
if(src[i]==padding_char)
src[i]='A';
}
for(int i=0;i<base_len;i+=4){
result[j++]=(findchr(table,src[i])<<2)+((findchr(table,src[i+1])& 0xF0)>>4);
result[j++]=((findchr(table,src[i+1])& 0x0F)<<4)+((findchr(table,src[i+2])& 0x3C)>>2);
result[j++]=((findchr(table,src[i+2])& 0x03)<<6)+(findchr(table,src[i+3]));
}
感受裏面這些與操做沒啥用啊,無論與不與,都是那幾位了
而後按照從表裏面找出來的位置進行位操做,這裏拿前面編碼後的 cXdlcg== 來舉例子
好比 'c' 在表中是第 28 位(00011100)向左移動 2 位,那他就是 01110000,再加上表中 'X' 是 23(00010111),向右移動 4 位獲得 00000001,二者相加獲得 01110001 即 113 也就是 'q'
剩下的也同樣:
01110000 + 00000111 = 01110111 = 119 = 'w'
01000000 + 00100101 = 01100101 = 101 = 'e'
到這裏,一輪就結束了,用了 src[0]、src[1]、src[2]、src[3],解碼出來 qwe
接下來 src[4] 到了 'c',00100011
01110000 + 00000010 = 01110010 = 114 = 'r'
00000000 + 00000000 = 00000000 = null
00000000 + 00000000 = 00000000 = null
解碼結束
C 語言文件:
https://pan.baidu.com/s/1mBQA9dT48Y1ZgnBUOui5lg
提取碼: g79b
ps.源碼是好久以前保存的,忘了是在哪裏找的了,又搜了一下估計是來自這裏:
https://eqqie.cn/index.php/laji_note/785/
本文分享自微信公衆號 - 陳冠男的遊戲人生(CGN-115)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。