base64 原理及轉換會變大的原因

以前用到base64有這麼幾個場景:

  1. 使用html2canvas 將html 轉成圖片的時候,html 裡面的跨域圖片無法生成圖片,所以將圖片先轉成base64再生成
  2. jpg之類的圖片有損壓縮,使用canvas.toDataUrl()
  3. webpack 打包時,為瞭減少 https(http) 的請求數量(主要是為瞭減少三次握手,如果是http1.1開啟瞭長連接或者http2.0/3.0之類的有多路復用,其實我覺得可以不用轉base64),將小於10k(好像是10k,記不清瞭)的圖片轉成base64打在代碼裡。

但是,圖片轉成base64,體積會變大33%,所以大點的圖片也不建議轉換。

那麼,轉成 base64 為什麼會變大呢?

還有為啥叫 base64, 不叫base16或者base24、base32呢?

針對上面的疑問,我們一步步來解釋,別急,老弟!

base64 生成步驟

假設我們有個單詞要轉成base64: Hello

1. 找到每個字母對應的ASCII值

ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符
0 NUT 32 (space) 64 @ 96
1 SOH 33 ! 65 A 97 a
2 STX 34 " 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 , 71 G 103 g
8 BS 40 ( 72 H 104 h
9 HT 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DCI 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 S 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 TB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 / 124 |
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 `
31 US 63 ? 95 _ 127 DEL

通過上表可以得知分別為:

2. 將 ASCII 值轉換為二進制

算數不好的同學(我)試試這個方法:

13c839f1168e9881a38e6d88f4c5bc81

通過上面可以知道,其實 ASCII 碼隻有128個,也就是 7位就夠瞭,但是存儲確是用的 8 位,每個都是在前面補0,其實已經浪費瞭一些空間。假如說以後字符補充到256個,就可以充分利用空間瞭。

3. 將 ASCII 的二級制值每6個一組,重新組裝(如果不足六位,在前面補0),並計算對應的10進制的值

那疑問來瞭,為什麼是6個一組?

首先常用字符有a-z、A-Z、0-9

這些字符總共 26 + 26 + 10 = 62個,另外有找瞭2個湊數的字符 + /

其實我覺得其他字符拿來湊數也是可以的,例如 -、#、[、]等。

2的6次方等於64,也就是6位就足以覆蓋全部的base64字符瞭,所以是6位。

但是存儲還是按8位一組來的,所以要在前面補2個零。

6 和 8 的最小公倍數是24,也就是3個字節,每 6 位一組,也就是4組,每組前面補2個0,湊夠8位。所以這個時候就變成瞭4個字節,也就是增加瞭33.33%

重新分組後新的值為:

85868b6bdfe27f181c0be25b831a1f3c

同樣計算過程為:

4. 接下來就是根據新的值在base64表查找對應的字符瞭

索引 對應字符 索引 對應字符 索引 對應字符 索引 對應字符

最後的結果為:

02922fd4801edb2087c870072846b751

這時候轉換的結果是SGVsbGP

因為規定不足4字節的要在後面補 =

所以結果為SGVsbGP=

本以為這樣就ok瞭,但是我去在線base64 加解密 算瞭下結果為 SGVsbG8=

什麼?最後一位是8? 看瞭下base64 表裡對用的值為60,也就是 parseInt(111100,2),仔細想瞭下,每三個字符一組,如果隻有兩個,那最後一個字符就是00000000,分組的時候 就變成瞭111100。所以糾正後的結果為:

表格地址獲取:http://docs.qq.com/doc/DU0tod0JXQ0J3UFRp

為什麼是Base64,可以是Base16或者Base512嗎?

前面已經說到ASCII碼有128個,即 2 的 7 次方,一個字節等於8個無符號位,這種情況下,已經浪費瞭 1 個符號位,Base64 是 6位,假如說我們用4位的,也就是2的4次方16,可以命名為Base16,這個時候轉換會有什麼後果呢? 相當於一個字節拆成2個字節,4和8最小公倍數為32,也就是4個字節一組,但是重新組裝後,長度變為原來的2倍,所以體積變為原來的2倍。這時候應該清楚為什麼是Base64瞭吧,就是為瞭減少空間的浪費。那可以發明Base256、或者Base512 這種東西來節省體積嗎?如果是Base256,也就是2的8次方,跟現在的位數一樣,但是用不同的符號代替,則可以保證在不增加體積的情況下完成轉換。如果是Base512,則是9位瞭,一個字節才8位,那就不行瞭。這麼說來Base64 還有優化空間,上限就是Base512,哪天我高興瞭,我也給編個Base512的表,發明Base512編碼,哈哈哈!!!

然而實際情況是我並沒有512個字符可以用

发表回复

相关推荐

腿部毛細血管擴張註射治療——助您恢復光潔腿部

​​腿部毛細血管擴張癥有什麼表現?很多女性發現自己腿上出現瞭藍色或紫色的小血管擴張,會擔心自己是否患有靜脈曲張。這種臨...

· 1小时前

推荐丨中国近代史书单

如果对于中国近现代史,你还是一个小白,那我认为你可以先从以下几本书开始,去了解中国近现代史。最开始我们需要的是先在脑 ...

· 1小时前

mac下镜像飞速安装Homebrew教程

Homebrew是一款包管理工具,目前支持macOS和linux系统。主要有四个部分组成: brew、homebrew-core 、homebrew-cask、homebre ...

· 1小时前

三分鐘帶你瞭解軟件工程

導LEAD語 軟件工程你瞭解嗎?軟件工程就是計算機科學與技術?No!No!No!雖然這個專業同學們聽得多,但是很...

· 1小时前

路網密度的高低對比——以上海和東京為例

所謂路網密度,是指區域道路總長度與區域面積之比,路網密度的高低是一個相對的說法。選取上海市中心路網比較密集的一個10平...

· 1小时前