美文网首页
golang bytes.buffer详解

golang bytes.buffer详解

作者: 豆瓣奶茶 | 来源:发表于2019-01-11 18:56 被阅读13次

    Buffer 介绍

    Buffer 是 bytes 包中的一个 type Buffer struct{…}
    A buffer is a variable-sized buffer of bytes with Read and Write methods. The zero value for Buffer is an empty buffer ready to use.
    (是一个变长的 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()) // [104 101 108 108 111]
        buf.WriteByte(s)
        fmt.Println(buf.Bytes())    // [104 101 108 108 111 63]
    }
    

    WriteRune

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

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

    结果

    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())  //hello world
    
        s3 := make([]byte,3)
        buff.Read(s3)
        fmt.Println(string(s3))  //hel,s3的容量为3,只能读3个
        fmt.Println(buff.String()) //lo world
    
        buff.Read(s3)  // 会把s3覆盖掉
        fmt.Println(string(s3))  // lo 
        fmt.Println(buff.String())  // world
    }
    

    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()) //[228 189 160 229 165 189 120 117 120 105 97 111 102 101 110 103]
        b1,n1,_ := buf1.ReadRune()
        fmt.Println(string(b1)) // 你
        fmt.Println(n1)
        
        
        buf := bytes.NewBufferString("hello")
        fmt.Println(buf.String())  //hello
        b,n,_:= buf.ReadRune()
        fmt.Println(n) // 1
        fmt.Println(string(b))  //h
        fmt.Println(buf.String())   //ello
    }
    

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

    func (b *Buffer) ReadRune() (r rune, size int, err error) {
        if b.empty() {
            // Buffer is empty, reset to recover space.
            b.Reset()
            return 0, 0, io.EOF
        }
        c := b.buf[b.off]
        if c < utf8.RuneSelf {   // 就是在这里判断,读取的第一个字符是不是Rune
            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()) //bob hello world
    }
    
    

    从缓冲器取出

    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
    }
    
    

    相关文章

      网友评论

          本文标题:golang bytes.buffer详解

          本文链接:https://www.haomeiwen.com/subject/uybarqtx.html