当前位置 博文首页 > golang bufio包中Write方法的深入讲解

    golang bufio包中Write方法的深入讲解

    作者:benben_2015 时间:2021-07-06 18:46

    前言

    bufio包实现了带缓冲的I/O,它封装了io.Reader和io.Writer对象,然后创建了另外一种对象(Reader或Writer)实现了相同的接口,但是增加了缓冲功能。

    首先来看没有缓冲功能的Write(os包中)方法,它会将数据直接写到文件中。

    package main
    
    import (
     "os"
     "fmt"
    )
    
    func main() {
     file, err := os.OpenFile("a.txt", os.O_CREATE|os.O_RDWR, 0666)
     if err != nil {
      fmt.Println(err)
     }
     defer file.Close()
    
     content := []byte("hello world!")
     if _, err = file.Write(content); err != nil {
      fmt.Println(err)
     }
     fmt.Println("write file successful")
    }

    接着看一个错误的使用带缓冲的Write方法例子,当下面的程序执行后是看不到写入的数据的。

    package main
    
    import (
      "os"
      "fmt"
      "bufio"
    )
    
    func main() {
      file, err := os.OpenFile("a.txt", os.O_CREATE|os.O_RDWR, 0666)
      if err != nil {
        fmt.Println(err)
      }
      defer file.Close()
    
      content := []byte("hello world!")
      newWriter := bufio.NewWriter(file)
      if _, err = newWriter.Write(content); err != nil {
        fmt.Println(err)
      }
      fmt.Println("write file successful")
    }

    为什么会在文件中看不到写入的数据呢,我们来看看bufio中的Write方法。

    func (b *Writer) Write(p []byte) (nn int, err error){
      for len(p) > b.Available() && b.err == nil {
        var n int
        if b.Buffered() == 0{
          n,b.err =b.wr.Write(p)
        }else {
          n = copy(b.buf[b.n:],p)
          b.n+=n
          b.Flush()
        }
        nn+=n
        p=p[n:]
      }
      if b.err!=nil {
        return nn, b.err
      }
      n:= copy(b.buf[b.n:],p)
      b.n+= n
      nn+=n
      return nn,nil
    }

    Write方法首先会判断写入的数据长度是否大于设置的缓冲长度,如果小于,则会将数据copy到缓冲中;当数据长度大于缓冲长度时,如果数据特别大,则会跳过copy环节,直接写入文件。其他情况依然先会将数据拷贝到缓冲队列中,然后再将缓冲中的数据写入到文件中。

    所以上面的错误示例,只要给其添加Flush()方法,将缓存的数据写入到文件中。

    package main
    
    import (
      "os"
      "fmt"
      "bufio"
    )
    
    func main() {
      file, err := os.OpenFile("./a.txt", os.O_CREATE|os.O_RDWR, 0666)
      if err != nil {
        fmt.Println(err)
      }
      defer file.Close()
    
      content := []byte("hello world!")
      newWriter := bufio.NewWriterSize(file, 1024)
      if _, err = newWriter.Write(content); err != nil {
        fmt.Println(err)
      }
      if err = newWriter.Flush(); err != nil {
        fmt.Println(err)
      }
      fmt.Println("write file successful")
    }

    总结

    jsjbwy
    下一篇:没有了