Golang bytes.buffer详解

栏目: IT技术 · 发布时间: 4年前

Buffer 介绍

Buffer 是 bytes 包中的一个 type Buffer struct{…}

(是一个变长的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一个 空的 buffer,但是可以使用)

Buffer 就像一个集装箱容器,可以存东西,取东西(存取数据)

创建缓冲器

func main() {
    buf1 := bytes.NewBufferString("hello")
    buf2 := bytes.NewBuffer([]byte("hello"))
    buf3 := bytes.NewBuffer([]byte{'h','e','l','l','o'})
    fmt.Printf("%v,%v,%v\n",buf1,buf2,buf3)
    fmt.Printf("%v,%v,%v\n",buf1.Bytes(),buf2.Bytes(),buf3.Bytes())

    buf4 := bytes.NewBufferString("")
    buf5 := bytes.NewBuffer([]byte{})
    fmt.Println(buf4.Bytes(),buf5.Bytes())
}

复制代码

输出

hello,hello,hello
[104 101 108 108 111],[104 101 108 108 111],[104 101 108 108 111]
[] []

复制代码

写入到缓冲器
buffer在new的时候是空的,也是可以直接Write的

Write

func (b *Buffer) Write(p []byte) (n int,err error)

复制代码
func main() {
s := []byte(" world")
buf := bytes.NewBufferString("hello")
fmt.Printf("%v,%v\n",buf.String(),buf.Bytes())
buf.Write(s)
fmt.Printf("%v,%v\n",buf.String(),buf.Bytes())
}

复制代码

结果

hello,[104 101 108 108 111]
hello world,[104 101 108 108 111 32 119 111 114 108 100]

复制代码

WriteString

func (b *Buffer) WriteString(s string)(n int,err error)

复制代码
func main() {
    s := " world"
    buf := bytes.NewBufferString("hello")
    fmt.Printf("%v,%v\n",buf.String(),buf.Bytes())
    buf.WriteString(s)
    fmt.Printf("%v,%v\n",buf.String(),buf.Bytes())
}

复制代码

结果

hello,[104 101 108 108 111]
hello world,[104 101 108 108 111 32 119 111 114 108 100]

复制代码

WriteByte

func (b *Buffer) WriteByte(c byte) error

复制代码
func main() {
    var s byte = '?'
    buf := bytes.NewBufferString("hello")
    fmt.Println(buf.Bytes()) 
    buf.WriteByte(s)
    fmt.Println(buf.Bytes())    
}

复制代码

WriteRune

func (b *Buffer) WriteRune(r Rune) (n int,err error)

复制代码
func main(){
   var s rune = '好'
   buf := bytes.NewBufferString("hello")
   fmt.Println(buf.String()) 
   buf.WriteRune(s)   
   fmt.Println(buf.String()) 
}

复制代码

结果

22909
[104 101 108 108 111]
[104 101 108 108 111 229 165 189]

复制代码

从缓冲器中写出

func main() {
    file,_ := os.Create("test.txt")
    buf := bytes.NewBufferString("hello world")
    buf.WriteTo(file)
}

复制代码

读出缓冲器

Read

func (b *Buffer) Read(p []byte)(n int,err error)

复制代码
func main() {
    s1 := []byte("hello")
    buff :=bytes.NewBuffer(s1)
    s2 := []byte(" world")
    buff.Write(s2)
    fmt.Println(buff.String())  

    s3 := make([]byte,3)
    buff.Read(s3)
    fmt.Println(string(s3))  
    fmt.Println(buff.String()) 

    buff.Read(s3)  
    fmt.Println(string(s3))  
    fmt.Println(buff.String())  
}

复制代码

ReadByte

返回缓冲器头部的第一个byte

func (b *Buffer) ReadByte() (c byte,err error)

复制代码
func main() {
    buf := bytes.NewBufferString("hello")
    fmt.Println(buf.String())  // hello
    b,_:= buf.ReadByte()
    fmt.Println(string(b))  //h
    fmt.Println(buf.String())   //ello
}

复制代码

ReadRun
ReadRune方法,返回缓冲器头部的第一个rune

func (b *Buffer) ReadRune() (r rune,size int,err error)

复制代码
func main() {

    buf1 := bytes.NewBufferString("你好xuxiaofeng")
    fmt.Println(buf1.Bytes()) 
    b1,n1,_ := buf1.ReadRune()
    fmt.Println(string(b1)) 
    fmt.Println(n1)
    
    
    buf := bytes.NewBufferString("hello")
    fmt.Println(buf.String())  
    b,n,_:= buf.ReadRune()
    fmt.Println(n) 
    fmt.Println(string(b))  
    fmt.Println(buf.String())   
}

复制代码

为什么n==3,而n1==1呢?我们看下ReadRune 的源码

func (b *Buffer) ReadRune() (r rune, size int, err error) {
    if b.empty() {
        
        b.Reset()
        return 0, 0, io.EOF
    }
    c := b.buf[b.off]
    if c < utf8.RuneSelf {   
        b.off++
        b.lastRead = opReadRune1
        return rune(c), 1, nil
    }
    r, n := utf8.DecodeRune(b.buf[b.off:])
    b.off += n
    b.lastRead = readOp(n)
    return r, n, nil
}

复制代码

ReadBytes
ReadBytes方法,需要一个byte作为分隔符,读的时候从缓冲器里找出第一个出现的分隔符,缓冲器头部开始到分隔符之间的byte返回。

func (b *Buffer) ReadBytes(delim byte) (line []byte,err error)

复制代码
func main() {
    var d byte = 'f'
    buf := bytes.NewBufferString("xuxiaofeng")
    fmt.Println(buf.String())

    b,_ :=buf.ReadBytes(d)
    fmt.Println(string(b))
    fmt.Println(buf.String())
}

复制代码

相当于有一个分隔符

ReadString
和readBytes方法类似

读入缓冲器
ReadFrom方法,从一个实现io.Reader接口的r,把r的内容读到缓冲器里,n返回读的数量

func (b *Buffer) ReadFrom(r io.Reader) (n int64,err error)

复制代码
func main(){
   file, _ := os.Open("text.txt")
   buf := bytes.NewBufferString("bob ")
   buf.ReadFrom(file)
   fmt.Println(buf.String()) 
}

复制代码

从缓冲器取出
Next方法,返回前n个byte(slice),原缓冲器变

func (b *Buffer) Next(n int) []byte

复制代码
func main() {
    buf := bytes.NewBufferString("helloworld")
    fmt.Println(buf.String())  // helloworld
    b := buf.Next(2)
    fmt.Println(string(b))  // he
}

复制代码

缓冲区原理介绍
go字节缓冲区底层以字节切片做存储,切片存在长度len与容量cap, 缓冲区写从长度len的位置开始写,当len>cap时,会自动扩容。缓冲区读会从内置标记off位置开始读(off始终记录读的起始位置),当off==len时,表明缓冲区已全部读完
并重置缓冲区(len=off=0),此外当将要内容长度+已写的长度(即len) <= cap/2时,缓冲区前移覆盖掉已读的内容(off=0,len-=off),从避免缓冲区不断扩容

func main() {
    byteSlice := make([]byte, 20) 
    byteSlice[0] = 1                                  // 将缓冲区第一个字节置1
    byteBuffer := bytes.NewBuffer(byteSlice)          // 创建20字节缓冲区 len = 20 off = 0
    c, _ := byteBuffer.ReadByte()                     // off+=1
    fmt.Printf("len:%d, c=%d\n", byteBuffer.Len(), c) // len = 20 off =1   打印c=1
    byteBuffer.Reset()                                // len = 0 off = 0
    fmt.Printf("len:%d\n", byteBuffer.Len())          // 打印len=0
    byteBuffer.Write([]byte("hello byte buffer"))     // 写缓冲区  len+=17
    fmt.Printf("len:%d\n", byteBuffer.Len())          // 打印len=17
    byteBuffer.Next(4)                                // 跳过4个字节 off+=4
    c, _ = byteBuffer.ReadByte()                      // 读第5个字节 off+=1
    fmt.Printf("第5个字节:%d\n", c)                    // 打印:111(对应字母o)    len=17 off=5
    byteBuffer.Truncate(3)                            // 将未字节数置为3        len=off+3=8   off=5
    fmt.Printf("len:%d\n", byteBuffer.Len())          // 打印len=3为未读字节数  上面len=8是底层切片长度
    byteBuffer.WriteByte(96)                          // len+=1=9 将y改成A
    byteBuffer.Next(3)                                // len=9 off+=3=8
    c, _ = byteBuffer.ReadByte()                      // off+=1=9    c=96
    fmt.Printf("第9个字节:%d\n", c)                    // 打印:96
}

复制代码

欢迎关注我们的微信公众号,每天学习 Go 知识

Golang bytes.buffer详解

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

大数据之眼

大数据之眼

[德]尤夫娜·霍夫施泰特 / 陈巍 / 浙江文艺出版社 / 2018-5-7 / 68.00元

德国狂销10万册的大数据商业应用畅销书,经典之作《大数据时代》的姊妹篇。 该书在德语国家促发了一场关于大数据,人工智能与人的关系建构的大讨论。 德国大数据与人工智能领域权威,首度为中国读者亲笔作序。 在后大数据时代,如何维护自己的隐私,如何巧妙利用资源获得更多金钱? 一部对大数据发展所产生的问题进行思考和规避的先知式作品。 当智能机器欲“优化”我们,入侵我们的生活,统......一起来看看 《大数据之眼》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具