go標准庫的學習-encoding/base64


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

導入方式:

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編碼后的字符串。

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
}

 


免責聲明!

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



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