golang bytes.buffer详解

栏目: Go · 发布时间: 5年前

内容简介: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 介绍

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
}

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

查看所有标签

猜你喜欢:

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

Design systems

Design systems

Not all design systems are equally effective. Some can generate coherent user experiences, others produce confusing patchwork designs. Some inspire teams to contribute to them, others are neglected. S......一起来看看 《Design systems》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

SHA 加密
SHA 加密

SHA 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换