go標準庫的學習-encoding/base64

參考:https://studygolang.com/pkgdochtml

導入方式:golang

import "encoding/base64"

base64實現了RFC 4648規定的base64編碼。Base64是網絡上最多見的用於傳輸8Bit字節碼的編碼方式之一,Base64就是一種基於64個可打印字符(即6Bits)來表示二進制數據(即8Bits)的方法。Base64編碼是從二進制到字符的過程,可用於在HTTP環境下傳遞較長的標識信息,這樣更適合放在URL中進行傳遞。此時,採用Base64編碼具備不可讀性,須要解碼後才能閱讀。正則表達式

該編碼的規則就是:數據庫

  • 把3個字符變成4個字符:方法就是先將3個8Bits(3*8=24Bits)的值分紅4個6Bits的值(4*6=24Bits),而後在這四個6Bits值前添加兩個0將其變爲8Bits的值,這樣就可以保證生成的4個值表示的值大小爲(0~63),便可以將其轉成對應的ASCII碼(64個可打印字符)舉例:
轉換前:          01110011 00110001 00110011
拆分紅4份:        011100 110011 000100 110011
高位補0:          00011100 00110011 00000100 00110011
對應的值爲:       28 51 4 51
轉成對應的ASCII碼: c z E z
  • 每76個字符加一個換行符
  • 最後的結束符也要處理
然而,標準的Base64並不適合直接放在URL裏傳輸,由於URL編碼器會把標準Base64中的「/」和「+」字符變爲形如「%XX」的形式,而這些「%」號在存入數據庫時還須要再進行轉換,由於ANSI SQL中已將「%」號用做通配符。
 
爲解決此問題,可採用一種用於URL的改進Base64編碼,它不只在末尾去掉填充的'='號,並將標準Base64中的「+」和「/」分別改爲了「-」和「_」,這樣就免去了在URL編解碼和數據庫存儲時所要做的轉換,避免了編碼信息長度在此過程當中的增長,並統一了數據庫、表單等處對象標識符的格式。
 
另有一種用於正則表達式的改進Base64變種,它將「+」和「/」改爲了「!」和「-」,由於「+」,「/」以及前面在IRCu中用到的「[」和「]」在正則表達式中均可能具備特殊含義。
 

type Encoding

type Encoding struct {
    // 內含隱藏或非導出字段
}

雙向的編碼/解碼協議,根據一個64字符的字符集定義,RFC 4648標準化了兩種字符集。默認字符集用於MIME(RFC 2045)和PEM(RFC 1421)編碼;另外一種用於URL和文件名,用'-'和'_'替換了'+'和'/'。緩存

func NewEncoding

func NewEncoding(encoder string) *Encoding

使用給出的字符集生成一個*Encoding,字符集必須是64字節的字符串。網絡

 

Variables 

var StdEncoding = NewEncoding(encodeStd)

RFC 4648定義的標準base64編碼字符集。函數

var URLEncoding = NewEncoding(encodeURL)

RFC 4648定義的另外一base64編碼字符集,用於URL和文件名。大數據

 

下面的兩個函數分別就是編碼和解碼的過程:編碼

func (*Encoding) EncodeToString

func (enc *Encoding) EncodeToString(src []byte) string

返回將src編碼後的字符串。spa

func (*Encoding) DecodeString

func (enc *Encoding) DecodeString(s string) ([]byte, error)

返回base64編碼的字符串s表明的數據。

舉例:

package main 
import(
    "fmt"
    "encoding/base64" ) func main() { msg := "Hello,world" //11個字符應該裝成15個base64編碼的字符 encoded := base64.StdEncoding.EncodeToString([]byte(msg)) fmt.Println(encoded) //SGVsbG8sd29ybGQ=,後面的=是做填充用的 decoded, err := base64.StdEncoding.DecodeString(encoded) if err != nil { fmt.Println("decode error:", err) return } fmt.Println(string(decoded))//Hello,world }

 

下面的方法不是將他們編碼成字符串:

解碼字符:

func (*Encoding) DecodedLen

func (enc *Encoding) DecodedLen(n int) int

返回n字節base64編碼的數據解碼後的最大長度。

func (*Encoding) Decode

func (enc *Encoding) Decode(dst, src []byte) (n int, err error)

將src的數據解碼後存入dst,最多寫DecodedLen(len(src))字節數據到dst,並返回寫入的字節數。 若是src包含非法字符,將返回成功寫入的字符數和CorruptInputError。換行符(\r、\n)會被忽略。

舉例:

package main 
import(
    "encoding/base64"
    "log"
    "fmt"
    "io"
)

func main() { 
    encoded := "Zm9vLGJhcg=="
    n := base64.StdEncoding.DecodedLen(len(encoded))//DecodedLen返回len(encoded)字節base64編碼的數據解碼後的最大長度
    fmt.Println(n) //9
    dbuf := make([]byte, n) 
    _, err :=base64.StdEncoding.Decode(dbuf, []byte(encoded))

    if err != nil && err != io.EOF {
        log.Fatal("Read failed", err)
    }
    fmt.Printf("decoded result : %s\n", dbuf) //decoded result : foo,bar
}

 

下面兩個代碼組合進行編碼:

func (*Encoding) EncodedLen

func (enc *Encoding) EncodedLen(n int) int

返回n字節數據進行base64編碼後的最大長度。

func (*Encoding) Encode

func (enc *Encoding) Encode(dst, src []byte)

將src的數據編碼後存入dst,最多寫EncodedLen(len(src))字節數據到dst,並返回寫入的字節數。

 函數會把輸出設置爲4的倍數,所以不建議對大數據流的獨立數據塊執行此方法,使用NewEncoder()代替。

舉例:

package main 
import(
    "encoding/base64"
    "fmt"
)

func main() { 
    decoded := "foo,bar"
    n := base64.StdEncoding.EncodedLen(len(decoded))//DecodedLen返回len(encoded)字節base64編碼的數據解碼後的最大長度
    fmt.Println(n) //12
    dbuf := make([]byte, n) 
    base64.StdEncoding.Encode(dbuf, []byte(decoded))

    fmt.Printf("encode result : %s\n", dbuf) //encode result : Zm9vLGJhcg==
}

 

 下面就是生成編碼器和解碼器的方法,其實和上面的Encode和Decode實現的效果同樣,在編碼的是大數據流時使用下面的方法:

func NewEncoder(可寫Write)

func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser

建立一個新的base64流編碼器。寫入的數據會在編碼後再寫入w,base32編碼每3字節執行一次編碼操做;寫入完畢後,使用者必須調用Close方法以便將未寫入的數據從緩存中刷新到w中。

舉例:

package main 
import(
    "encoding/base64"
    "os"
)

func main() { 
    input := []byte("foo,bar")
    encoder := base64.NewEncoder(base64.StdEncoding, os.Stdout) //生成一個編碼器,會將調用Write()寫入的值編碼後寫到os.Stdout中
    encoder.Write(input)

    encoder.Close()
    //返回Zm9vLGJhcg==
}

 

func NewDecoder(可讀-Read)

func NewDecoder(enc *Encoding, r io.Reader) io.Reader

建立一個新的base64流解碼器。

舉例:

package main 
import(
    "encoding/base64"
    "strings"
    "log"
    "fmt"
    "io"
)

func main() { 
    encoded := "Zm9vLGJhcg=="
    decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(encoded))
    n := base64.StdEncoding.DecodedLen(len(encoded))//DecodedLen返回len(encoded)字節base64編碼的數據解碼後的最大長度
    fmt.Println(n) //9
    dbuf := make([]byte, n) 
    _, err := decoder.Read(dbuf)//將讀取的解碼後的值寫到dbuf中
    if err != nil && err != io.EOF {
        log.Fatal("Read failed", err)
    }
    fmt.Printf("decoded result : %s\n", dbuf) //decoded result : foo,bar
}
相關文章
相關標籤/搜索