計算機編碼規則之:Base64編碼


簡介

我們知道計算機中的文件可以分為兩種,一種是人肉眼可讀的文本類文件,一種是肉眼不可讀的二進制文件。一般來說二進制文件如果用文本編輯器打開的話會顯示亂碼,並且二進制文件和文本文件的存儲和傳輸方式是不一樣的,那么有沒有什么辦法將二進制文件轉換成為文本文件進行傳輸或者存儲呢?答案是肯定的。

這種編碼方式就是我們今天要講到的Base64編碼。

Base64和它的編碼原理

Base64是一種將二進制編碼格式轉換為text編碼的一種形式。我們知道二進制編碼是0和1的形式,它的單位通常是一個字節,也就是8bits,每個bit表示的是0或者1。

而文本編碼的格式有很多種,最早也就是最簡單的編碼格式就是ASCII編碼,ASCII編碼的全稱是American Standard Code for Information Interchange,也就是美國信息交換標准代碼,它主要表示的是常用的一些西歐字符。

ASCII的編碼范圍是0x00-0x7F,用十進制來表示就是0-127,總共128個字符,剛好是7bits表示的范圍。

ASCII編碼中包含了33個控制字符和95個可打印的字符,如下所示:

ASCII碼 含義 ASCII碼 含義
16進制 10進制 2進制 16進制 10進制 2進制
0x00 0 0 NUL 空 0x40 64 1000000 @
0x01 1 1 SOH 標題開始 0x41 65 1000001 A
0x02 2 10 STX 正文開始 0x42 66 1000010 B
0x03 3 11 ETX 正文結束 0x43 67 1000011 C
0x04 4 100 EOT 傳輸結束 0x44 68 1000100 D
0x05 5 101 ENQ 詢問字符 0x45 69 1000101 E
0x06 6 110 ACK 承認 0x46 70 1000110 F
0x07 7 111 BEL 報警 0x47 71 1000111 G
0x08 8 1000 BS 退一格 0x48 72 1001000 H
0x09 9 1001 HT 橫向制表 0x49 73 1001001 I
0x0A 10 1010 LF 換行 0x4A 74 1001010 J
0x0B 11 1011 VT 垂直制表 0x4B 75 1001011 K
0x0C 12 1100 FF 走紙控制 0x4C 76 1001100 L
0x0D 13 1101 CR 回車 0x4D 77 1001101 M
0x0E 14 1110 SO 移位輸出 0x4E 78 1001110 N
0x0F 15 1111 SI 移位輸入 0x4F 79 1001111 O
0x10 16 10000 DLE 數據鏈路轉義 0x50 80 1010000 P
0x11 17 10001 DC1 設備控制1 0x51 81 1010001 Q
0x12 18 10010 DC2 設備控制2 0x52 82 1010010 R
0x13 19 10011 DC3 設備控制3 0x53 83 1010011 S
0x14 20 10100 DC4 設備控制4 0x54 84 1010100 T
0x15 21 10101 NAK 否定 0x55 85 1010101 U
0x16 22 10110 SYN 空轉同步 0x56 86 1010110 V
0x17 23 10111 ETB 信息組傳送結束 0x57 87 1010111 W
0x18 24 11000 CAN 作廢 0x58 88 1011000 X
0x19 25 11001 EM 紙盡 0x59 89 1011001 Y
0x1A 26 11010 SUB 換置 0x5A 90 1011010 Z
0x1B 27 11011 ESC 換碼 0x5B 91 1011011 [
0x1C 28 11100 FS 文字分隔符 0x5C 92 1011100 \
0x1D 29 11101 GS 組分隔符 0x5D 93 1011101 ]
0x1E 30 11110 RS 記錄分隔符 0x5E 94 1011110 ^
0x1F 31 11111 US 單元分隔符 0x5F 95 1011111 _
0x20 32 100000 (space) 0x60 96 1100000 `
0x21 33 100001 0x61 97 1100001 a
0x22 34 100010 0x62 98 1100010 b
0x23 35 100011 # 0x63 99 1100011 c
0x24 36 100100 $ 0x64 100 1100100 d
0x25 37 100101 % 0x65 101 1100101 e
0x26 38 100110 & 0x66 102 1100110 f
0x27 39 100111 ' 0x67 103 1100111 g
0x28 40 101000 ( 0x68 104 1101000 h
0x29 41 101001 ) 0x69 105 1101001 i
0x2A 42 101010 * 0x6A 106 1101010 j
0x2B 43 101011 + 0x6B 107 1101011 k
0x2C 44 101100 , 0x6C 108 1101100 l
0x2D 45 101101 - 0x6D 109 1101101 m
0x2E 46 101110 . 0x6E 110 1101110 n
0x2F 47 101111 / 0x6F 111 1101111 o
0x30 48 110000 0 0x70 112 1110000 p
0x31 49 110001 1 0x71 113 1110001 q
0x32 50 110010 2 0x72 114 1110010 r
0x33 51 110011 3 0x73 115 1110011 s
0x34 52 110100 4 0x74 116 1110100 t
0x35 53 110101 5 0x75 117 1110101 u
36 54 110110 6 0x76 118 1110110 v
0x37 55 110111 7 0x77 119 1110111 w
0x38 56 111000 8 0x78 120 1111000 x
0x39 57 111001 9 0x79 121 1111001 y
0x3A 58 111010 : 0x7A 122 1111010 z
0x3B 59 111011 ; 0x7B 123 1111011 {
0x3C 60 111100 < 0x7C 124 1111100 |
0x3D 61 111101 = 0x7D 125 1111101 }
0x3E 62 111110 > 0x7E 126 1111110 ~
0x3F 63 111111 ? 0x7F 127 1111111 DEL 刪除

Base64就是從ASCII編碼中挑選出64個字符和二進制一個字節8bits進行映射,這也就是Base64中64的含義。為什么要選擇ASCII編碼呢?這是因為ASCII編碼是最早出現的編碼形式,幾乎所有的計算機應用都對其完全支持,不會出現數據傳輸過程中的內容轉換,非常的安全。

當然Base64編碼也有多種編碼形式,比如在MIME中,Base64選擇的是A-Z, a-z, 和 0-9 總共62個字符,再加上其他自選的兩個字符組成了64個編碼字符。

64個字符用二進制表示是6bits,而常用的二進制使用一個字節來表示,也就是8bits,那么問題來了,怎么將8bits的二進制用6bits的Base64字符來表示呢?

很簡單,我們只需要將3個8bits連接起來,變成24bits,這樣就可以用4個Base64來表示了。

為什么必須對二進制進行轉換呢?這是因為互聯網中的某些傳輸協議只支持某些特定的字符集,如果是其他的字符集是不支持的。比如說常用的發送電子郵件的附件。因為SMTP協議最開始設計的時候是支持7 位 ASCII 字符,所以如果要傳輸文件的話,我們需要對文件進行編碼之后再進行傳輸。

另外Base64的一種用法就是在HTML中將圖片嵌入到網頁中,從而實現圖片的展示。

雖然Base64很好用,但是因為其只能使用6bits的字符映射集,所以會造成數據映射的損失,從而導致二進制文件編碼過后文件體積變大的缺點。

Base64的變體

Base64簡單點說就是bit到bit之間的映射,那么肯定不止一種映射方式,我們來看下Base64編碼方式的各種變體,通常來說前62位基本上是一樣的,不同之處在后面兩個字符,以及用於填充的字符(這在某些協議中可能是強制性的,或者在其他協議中可能被刪除)。

下表是常見的Base64編碼的變體:

編碼名稱 編碼字符 編碼字符 編碼字符
第62位 第63位 補全符
RFC 1421: Base64 for Privacy-Enhanced Mail (deprecated) + / = mandatory
RFC 2045: Base64 transfer encoding for MIME + / = mandatory
RFC 2152: Base64 for UTF-7 + / No
RFC 3501: Base64 encoding for IMAP mailbox names + , No
RFC 4648: base64 (standard) + / = optional
RFC 4648: base64url (URL- and filename-safe standard) - _ = optional
RFC 4880: Radix-64 for OpenPGP + / = mandatory

Base64的編碼細節

上一節我們講到了Base64編碼的基本原則和一些常見的變體,那么到底是如何進行映射的呢?

本節我們會以Base64的標准形式RFC 4648為例來進行詳細的講解。

RFC 4648選擇+和/這兩個字符作為編碼中的第62位和63位,並且選擇=作為補全字符。

首先來觀察一下RFC 4648的映射表:

索引 二進制 字符 索引 二進制 Char 索引 二進制 Char 索引 二進制 Char
0 000000 A 16 010000 Q 32 100000 g 48 110000 w
1 000001 B 17 010001 R 33 100001 h 49 110001 x
2 000010 C 18 010010 S 34 100010 i 50 110010 y
3 000011 D 19 010011 T 35 100011 j 51 110011 z
4 000100 E 20 010100 U 36 100100 k 52 110100 0
5 000101 F 21 010101 V 37 100101 l 53 110101 1
6 000110 G 22 010110 W 38 100110 m 54 110110 2
7 000111 H 23 010111 X 39 100111 n 55 110111 3
8 001000 I 24 011000 Y 40 101000 o 56 111000 4
9 001001 J 25 011001 Z 41 101001 p 57 111001 5
10 001010 K 26 011010 a 42 101010 q 58 111010 6
11 001011 L 27 011011 b 43 101011 r 59 111011 7
12 001100 M 28 011100 c 44 101100 s 60 111100 8
13 001101 N 29 011101 d 45 101101 t 61 111101 9
14 001110 O 30 011110 e 46 101110 u 62 111110 +
15 001111 P 31 011111 f 47 101111 v 63 111111 /
補全符 =

我們來以單詞man為例,來觀察一下Base64的編碼流程。

man這個單詞在ASCII中分別用77, 97和110表示,轉換成為二進制就是01001101, 01100001 和 01101110。

將上面的三個二進制合並在一起就成了:010011010110000101101110, 總共24-bit,從上面的表中選擇出對應的字符,所以我們可以得到man經過base64編碼之后得到:TWFu。

上面的例子中,man剛好是3個字符,也就是24個bits,可以用base64完整的表示。如果我們只有ma這兩個字符,應該怎么進行編碼呢?

和上面一樣,ma的二進制分別是01001101, 01100001,合並起來就是0100110101100001。

但是上面的bits只有16位,因為一個base64是6bits,所以可以用3個base64來表示,因為原始的bits少了兩位,所以用0來補全:

0100110101100001+00 = 010011010110000100。

010011010110000100轉換成為base64就是TWE,因為base64編碼需要4個字符,所以最后的字符用=來補全,也就是說me經過base64之后變成TWE=。

總結

以上就是Base64的基本含義和轉換規則,其實協議很簡單,將要轉換的數據變成二進制,然后對照轉換表格進行轉換和補全即可。

本文已收錄於 http://www.flydean.com/18-base64-encoding/

最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM