根据 RFC2045 限制行长度的 Base64 编码

RFC2045 第 6.8 节规定 Base64 输出的最大编码行长度应为 76 个字符或更少。


Golang 流编写器base64.NewEncoder没有任何行分割选项,如此处所示。


package main


import (

    "encoding/base64"

    "io"

    "os"

    "strings"

)



// See https://www.ietf.org/rfc/rfc2045.txt, section 6.8 for notes on maximum line length of 76 characters

func main() {

    data := "It is only the hairs on a gooseberry that prevent it from being a grape! This is long enough to need a line split"

    rdr := strings.NewReader(data)

    wrt := base64.NewEncoder(base64.StdEncoding, os.Stdout)

    io.Copy(wrt, rdr)

}

输出是


SXQgaXMgb25seSB0aGUgaGFpcnMgb24gYSBnb29zZWJlcnJ5IHRoYXQgcHJldmVudCBpdCBmcm9tIGJlaW5nIGEgZ3JhcGUhIEl0IGlzIG9ubHkgdGhlIGhhaXJzIG9uIGEgZ29vc2ViZXJyeSB0aGF0IHByZXZlbnQgaXQgZnJvbSBiZWluZyBhIGdyYXBl

是否有基于流的分割线解决方案?MIME库仅提供基于字符串的编码选项。


侃侃尔雅
浏览 213回答 1
1回答

梦里花落0921

这是我尝试创建一个简单的Writer. 它考虑到不同数量的输入数据,具有可配置的块长度和分隔符序列。它使用字节片写入块,这有望提高效率。package mainimport (&nbsp; &nbsp; "encoding/base64"&nbsp; &nbsp; "io"&nbsp; &nbsp; "os"&nbsp; &nbsp; "strings")func min(a, b int) int {&nbsp; &nbsp; if a < b {&nbsp; &nbsp; &nbsp; &nbsp; return a&nbsp; &nbsp; }&nbsp; &nbsp; return b}type linesplitter struct {&nbsp; &nbsp; len&nbsp; &nbsp;int&nbsp; &nbsp; count int&nbsp; &nbsp; sep&nbsp; &nbsp;[]byte&nbsp; &nbsp; w&nbsp; &nbsp; &nbsp;io.Writer}// NewWriter that splits input every len bytes with a sep byte sequence, outputting to writer wfunc (ls *linesplitter) NewWriter(len int, sep []byte, w io.Writer) io.WriteCloser {&nbsp; &nbsp; return &linesplitter{len: len, count: 0, sep: sep, w: w}}// Split a line in to ls.len chunks with separatorfunc (ls *linesplitter) Write(in []byte) (n int, err error) {&nbsp; &nbsp; writtenThisCall := 0&nbsp; &nbsp; readPos := 0&nbsp; &nbsp; // Leading chunk size is limited by: how much input there is; defined split length; and&nbsp; &nbsp; // any residual from last time&nbsp; &nbsp; chunkSize := min(len(in), ls.len-ls.count)&nbsp; &nbsp; // Pass on chunk(s)&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; ls.w.Write(in[readPos:(readPos + chunkSize)])&nbsp; &nbsp; &nbsp; &nbsp; readPos += chunkSize // Skip forward ready for next chunk&nbsp; &nbsp; &nbsp; &nbsp; ls.count += chunkSize&nbsp; &nbsp; &nbsp; &nbsp; writtenThisCall += chunkSize&nbsp; &nbsp; &nbsp; &nbsp; // if we have completed a chunk, emit a separator&nbsp; &nbsp; &nbsp; &nbsp; if ls.count >= ls.len {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ls.w.Write(ls.sep)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writtenThisCall += len(ls.sep)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ls.count = 0&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; inToGo := len(in) - readPos&nbsp; &nbsp; &nbsp; &nbsp; if inToGo <= 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break // reached end of input data&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // Determine size of the NEXT chunk&nbsp; &nbsp; &nbsp; &nbsp; chunkSize = min(inToGo, ls.len)&nbsp; &nbsp; }&nbsp; &nbsp; return writtenThisCall, nil}func (ls *linesplitter) Close() (err error) {&nbsp; &nbsp; return nil}// See https://www.ietf.org/rfc/rfc2045.txt, section 6.8 for notes on maximum line length of 76 charactersfunc main() {&nbsp; &nbsp; data := "It is only the hairs on a gooseberry that prevent it from being a grape! This is long enough to need a line split"&nbsp; &nbsp; shortData := "hello there"&nbsp; &nbsp; var ls linesplitter&nbsp; &nbsp; lsWriter := ls.NewWriter(76, []byte("\r\n"), os.Stdout)&nbsp; &nbsp; wrt := base64.NewEncoder(base64.StdEncoding, lsWriter)&nbsp; &nbsp; for i := 0; i < 10; i++ {&nbsp; &nbsp; &nbsp; &nbsp; io.Copy(wrt, strings.NewReader(shortData))&nbsp; &nbsp; &nbsp; &nbsp; io.Copy(wrt, strings.NewReader(data))&nbsp; &nbsp; &nbsp; &nbsp; io.Copy(wrt, strings.NewReader(shortData))&nbsp; &nbsp; }}...欢迎提出意见/改进。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go