Go中bytes.Buffer理解

393 阅读3分钟

Go中bytes.Buffer理解

buffer

前言

最近操作文件,进行优化使用到了buffer。好像也不太了解这个,那么就梳理下,buffer的使用。

例子

我的场景:使用xml拼接了office2003的文档。写入到buffer,然后处理完了,转存到文件里面。


// 初始化 func NewBuff() *Buff { b := bytes.NewBuffer([]byte{}) return &Buff{ Buffer: b, Writer: bufio.NewWriter(b), } } 
func (b *Buff) WriteString(str string) error { _, err := b.Writer.WriteString(str) return err }
func (b *Buff) SaveAS(name string) error { file, err := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666) if err != nil { return err } 
defer file.Close() 
if err := b.Writer.Flush(); 
err != nil { return nil } _, err = b.Buffer.WriteTo(file) return err } func main() { var b = NewBuff() b.WriteString("haah") } 123456789101112131415161718192021222324252627282930313233343536373839

了解下bytes.buffer

bytes.buffer是一个缓冲byte类型的缓冲器,这个缓冲器里存放着都是byte。

如何创建bytes.buffer

放几种创建的方式

buf1 := bytes.NewBufferString("hello") fmt.Println(buf1) 
buf2 := bytes.NewBuffer([]byte("hello")) fmt.Println(buf2) 
buf3 := bytes.NewBuffer([]byte{byte('h'), byte('e'), byte('l'), byte('l'), 

byte('o')}) fmt.Println(buf3) // 以上三者等效 
buf4 := bytes.NewBufferString("") fmt.Println(buf4)
buf5 := bytes.NewBuffer([]byte{}) fmt.Println(buf5) // 以上两者等效

查看源码可知

func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} } func NewBufferString(s string) *Buffer { return &Buffer{buf: []byte(s)} }

NewBufferString也是将参数转成[]byte()。然后,初始化Buffer。

bytes.buffer的数据写入

写入string

buf := bytes.NewBuffer([]byte{}) buf.WriteString("小花猫") fmt.Println(buf.String())

写入[]byte

buf := bytes.NewBuffer([]byte{}) s := []byte("小黑猫") buf.Write(s) fmt.Println(buf.String())

写入byte

var b byte = '?' buf.WriteByte(b) fmt.Println(buf.String())

写入rune

var r rune = '小' buf.WriteRune(r) fmt.Println(buf.String())

从文件写入

file, err := os.Open("./buffer/test.txt")
//test.txt的内容是“world” if err != nil { fmt.Println(err) } 
defer file.Close() fmt.Println(file.Sync())
buf := bytes.NewBufferString("hello ") 
buf.ReadFrom(file) //将text.txt内容追加到缓冲器的尾部 

fmt.Println(buf.String()) //打印“hello world”

数据写出

写出数据到io.Writer

file, _ := os.Open("text.txt") buf := bytes.NewBufferString("hello") buf.WriteTo(file) // hello写到text.txt文件中了

os.File就是实现io.Writer

Read

bufRead := bytes.NewBufferString("hello") fmt.Println(bufRead.String()) var sRead = make([]byte, 3) 
// 定义读出的[]byte为3,表示一次可读出3个byte bufRead.Read(sRead) // 读出 fmt.Println(bufRead.String()) 
// 打印结果为lo,因为前三个被读出了 fmt.Println(string(sRead)) // 打印结果为hel,读取的是hello的前三个字母 bufRead.Read(sRead) 
// 接着读,但是bufRead之剩下lo,所以只有lo被读出了 fmt.Println(bufRead.String())
// 打印结果为空 fmt.Println(string(sRead)) 
// 打印结果lol,前两位的lo表示的本次的读出,因为bufRead只有两位,后面的l还是上次的读出结果 ReadByte buf := bytes.NewBufferString("hello") fmt.Println(buf.String()) 
// buf.String()方法是吧buf里的内容转成string,>以便于打印 b, _ := buf.ReadByte() 
// 读取第一个byte,赋值给b fmt.Println(buf.String()) 
// 打印 ello,缓冲器头部第一个h被拿掉 fmt.Println(string(b)) // 打印 h ReadRune buf := bytes.NewBufferString("好hello") fmt.Println(buf.String()) // buf.String()方法是吧buf里的内容转成string,>以便于打印 b, n, _ := buf.ReadRune() 
// 读取第一个rune,赋值给b fmt.Println(buf.String()) // 打印 hello fmt.Println(string(b)) // 打印中文字: 好,缓冲器头部第一个“好”被拿掉 fmt.Println(n)
// 打印3,“好”作为utf8储存占3个byte b, n, _ = buf.ReadRune() // 再读取第一个rune,赋值给b fmt.Println(buf.String()) // 打印 ello fmt.Println(string(b)) // 打印h,缓冲器头部第一个h被拿掉 fmt.Println(n) // 打印 1,“h”作为utf8储存占1个byte

ReadBytes

ReadBytes和ReadByte是有区别的。ReadBytes需要一个分隔符来对buffer进行分割读取。

var d byte = 'e' //分隔符为e buf := bytes.NewBufferString("hello") fmt.Println(buf.String()) // buf.String()方法是吧buf里的内容转成string,以便于打印 b, _ := buf.ReadBytes(d) // 读到分隔符,并返回给b fmt.Println(buf.String()) // 打印 llo,缓冲器被取走一些数据 fmt.Println(string(b)) // 打印 he,找到e了,将缓冲器从头开始,到e的内容都返回给b

ReadString

ReadString和ReadBytes一样,也是需要一个分隔符进行,buffer

var d byte = 'e' //分隔符为e buf := bytes.NewBufferString("hello") 
fmt.Println(buf.String()) 
// buf.String()方法是吧buf里的内容转成string,
以便于打印 b, _ := buf.ReadString(d) // 读到分隔符,并返回给b fmt.Println(buf.String()) 
// 打印 llo,缓冲器被取走一些数据 fmt.Println(b) 
// 打印 he,找到e了,将缓冲器从头开始,到e的内容都返回给b

Next

使用Next可依次读出固定长度的内容

buf := bytes.NewBufferString("hello")
fmt.Println(buf.String()) b := buf.Next(2)
// 重头开始,取2个 fmt.Println(buf.String()) 
// 变小了 fmt.Println(string(b)) // 打印he