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

前言

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")
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • golang中bufio.SplitFunc的深入理解

    前言 bufio模块是golang标准库中的模块之一,主要是实现了一个读写的缓存,用于对数据的读取或者写入操作.该模块在多个涉及io的标准库中被使用,比如http模块中使用buffio来完成网络数据的读写,压缩文件的zip模块利用bufio来操作文件数据的读写等. golang的bufio包里面定以的SplitFunc是一个比较重要也比较难以理解的东西,本文希望通过结合简单的实例介绍SplitFunc的工作原理以及如何实现一个自己的SplitFunc. 一个例子 在bufio包里面定义了一些常用

  • 详解golang中bufio包的实现原理

    最近用golang写了一个处理文件的脚本,由于其中涉及到了文件读写,开始使用golang中的 io 包,后来发现golang 中提供了一个bufio的包,使用这个包可以大幅提高文件读写的效率,于是在网上搜索同样的文件读写为什么bufio 要比io的读写更快速呢?根据网上的资料和阅读源码,以下来详细解释下bufio的高效如何实现的. bufio 包介绍  bufio包实现了有缓冲的I/O.它包装一个io.Reader或io.Writer接口对象,创建另一个也实现了该接口,且同时还提供了缓冲和一些文

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

    前言 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

  • Maven引入本地Jar包并打包进War包中的方法

    1.概述 在平时的开发中,有一些Jar包因为种种原因,在Maven的中央仓库中没有收录,所以就要使用本地引入的方式加入进来. 2. 拷贝至项目根目录 项目根目录即pom.xml文件所在的同级目录,可以在项目根目录下创建文件夹lib,如下图所示: 这4个Jar包是识别网页编码所需的包. 3. 配置pom.xml,依赖本地Jar 配置Jar的dependency,包括groupId,artifactId,version三个属性,同时还要包含scope和systemPath属性,分别指定Jar包来源于

  • go语言中sort包的实现方法与应用详解

    前言 Go语言的 sort 包实现了内置和用户定义类型的排序,sort包中实现了3种基本的排序算法:插入排序.快排和堆排序.和其他语言中一样,这三种方式都是不公开的,他们只在sort包内部使用.所以用户在使用sort包进行排序时无需考虑使用那种排序方式,sort.Interface定义的三个方法:获取数据集合长度的Len()方法.比较两个元素大小的Less()方法和交换两个元素位置的Swap()方法,就可以顺利对数据集合进行排序.sort包会根据实际数据自动选择高效的排序算法. 之前跟大家分享了

  • 详解Golang 与python中的字符串反转

    详解Golang 与python中的字符串反转 在go中,需要用rune来处理,因为涉及到中文或者一些字符ASCII编码大于255的. func main() { fmt.Println(reverse("Golang python")) } func reverse(src string) string { dst := []rune(src) len := len(dst) var result []rune result = make([]rune, 0) for i := le

  • Golang开发命令行之flag包的使用方法

    目录 1.命令行工具概述 2.flag包介绍 3.flag包命令行参数的定义 4.flag包命令行参数解析 5.flag包命令行帮助 6.flag定义短参数和长参数 7.示例 1.命令行工具概述 日常命令行操作,相对应的众多命令行工具是提高生产力的必备工具,鼠标能够让用户更容易上手,降低用户学习成本. 而对于开发者,键盘操作模式能显著提升生产力,还有在一些专业工具中, 大量使用快捷键代替繁琐的鼠标操作,能够使开发人员更加专注于工作,提高效率,因为键盘操作模式更容易产生肌肉记忆 举个栗子:我司业务

  • golang time包下定时器的实现方法

    golang time包 和python一样,golang时间处理还是比较方便的,以下介绍了golang 时间日期,相关包 "time"的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍. 时间戳 当前时间戳 fmt.Println(time.Now().Unix()) # 1389058332 str格式化时间 当前格式化时间 fmt.Println(time.Now().Format("2006-01-02 15:04:05")) // 这

  • 浅谈golang package中init方法的多处定义及运行顺序问题

    在不了解这个问题之前,在网上搜索一下竟然搜出了两个完全相反的结果,所以打算自己测试下这个问题. 首先给出结论: 在同一个package中,可以多个文件中定义init方法 在同一个go文件中,可以重复定义init方法 在同一个package中,不同文件中的init方法的执行按照文件名先后执行各个文件中的init方法 在同一个文件中的多个init方法,按照在代码中编写的顺序依次执行不同的init方法 下面看下测试的代码: 在当前目录下新建main.go及testinit目录,在testinit目录下

  • Golang 统计字符串中数字字母数量的实现方法

    目录 1.需求说明 2.实现 2.1 ASCII 码值法 2.2 正则表达式 3.性能对比 4.小结 参考文献 1.需求说明 记录一下项目对用户 UGC 文本进行字数限制的具体实现. 不同的产品,出于种种原因,一般都会对用户输入的文本内容做字数限制. 出于产品定位,比如 140 字符限制的 Twitter,让内容保持简洁凝练,易于阅读: 出于用户的阅读体验,过多的文字会造成阅读疲劳,合适的字数能够提高阅读舒适度: 出于技术与成本的考虑,不设上限的 UGC 内容会引发一些潜在的问题,比如增加存储的

  • java打包成jar并执行jar包中指定的main方法

    java打包成jar jar -cvf [jar包的名字] [需要打包的文件] 执行jar包中的main方法 java -jar ****.jar 执行后总是运行指定的主方法,如果 jar 中有多个 main 方法,那么如何运行指定的 main 方法呢? 用下面的命令试试看: java -classpath ****.jar ****.****.className [args] "****.****"表示"包名": "className"表示&q

随机推荐