前端同學對base64的認識,往往是 圖片可以用base64的方式來顯示.
其實我們前後端最常用的jwt驗證也是base64這種編碼的.
今天就單獨說base64編碼本身.
宣告
base64編碼我們要看的是他的過程和標準.下面舉例程式碼非js,但基本思路都是一樣的,因為標準就一個.
上程式碼
const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
// The encoding pads the output to a multiple of 4 bytes,
// so Encode is not appropriate for use on individual blocks
// of a large data stream. Use NewEncoder() instead.
func (enc *Encoding) Encode(dst, src []byte) {
if len(src) == 0 {
return
}
di, si := 0, 0
// 能被3整除的最大的數
// 標準中說明3個位元組要被轉換為 4個 6bits的組
// a 24-bit input group is formed by concatenating 3 8-bit input groups.
n := (len(src) / 3) * 3
// n個組,每組是3個位元組
for si < n {
// Convert 3x 8bit source bytes into 4 bytes
// 第一個8bits後面+16個0
// 第二個8bits後面+8個0
// 第三個8bits
// val -> [第一個8bits][第二個8bits][第三個8bits] 連線在一起 24bits
val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
// 取出最左6bits給 dst[0]
// 7-12 中間6bits給dst[1]
// 依次放入dst 共4組,每組6bits
dst[di+0] = enc.encode[val>>18&0x3F]
dst[di+1] = enc.encode[val>>12&0x3F]
dst[di+2] = enc.encode[val>>6&0x3F]
dst[di+3] = enc.encode[val&0x3F]
si += 3
di += 4
}
// 不能被整除剩餘的位元組
// 有的字可能2個或者1個位元組就能表示了
// (1) The final quantum of encoding input is an integral multiple of 24
// bits; here, the final unit of encoded output will be an integral
// multiple of 4 characters with no "=" padding.
remain := len(src) - si
if remain == 0 {
return
}
// Add the remaining small block
// 拿到字元對應的ascii碼,並左移16位 相當於 * 2^16
// val是多出的第一個位元組
val := uint(src[si+0]) << 16
// 如果多出2個位元組的情況 val 就是 [多出的第一個8bits][多出的第二個8bits][8個0] 共24bits連線
if remain == 2 {
val |= uint(src[si+1]) << 8
}
// 取最左6bits
// 6位都是1也就是63,在64內,拿到對應的字元進入dst
dst[di+0] = enc.encode[val>>18&0x3F]
// 取中間6bits
dst[di+1] = enc.encode[val>>12&0x3F]
switch remain {
case 2:
// (3) The final quantum of encoding input is exactly 16 bits; here, the
// final unit of encoded output will be three characters followed by
// one "=" padding character.
// 取第三個6bits出來
dst[di+2] = enc.encode[val>>6&0x3F]
if enc.padChar != NoPadding {
// 根據標準要+一個pad
dst[di+3] = byte(enc.padChar)
}
case 1:
// (2) The final quantum of encoding input is exactly 8 bits; here, the
// final unit of encoded output will be two characters followed by
// two "=" padding characters.
if enc.padChar != NoPadding {
// 根據標準+2個pad
dst[di+2] = byte(enc.padChar)
dst[di+3] = byte(enc.padChar)
}
}
}
複製程式碼
上面程式碼只是針對標準的encode做出了說明.
對於URLencode 會有些不同
主要區別是
const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" 請對比上面的標準字符集 const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
想看具體標準內容的,請走傳送門 tools.ietf.org/html/rfc464…