✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:Go语言开发零基础到高阶实战
景天的主页:景天科技苑
文章目录
Go语言中bufio
bufio是Go语言标准库中的一个重要包,它提供了带缓冲的I/O操作,用于包装io.Reader或io.Writer对象,以减少I/O操作的次数,从而提高读写性能。本文将结合实际案例,详细讲解bufio在Go语言中的用法。
Go语言自带的IO操作包。bufio,使用这个包可以大幅提升文件的读写效率。
buf: 缓冲区.
io操作效率本身是还可以的,频繁访问本地磁盘文件(效率低)
所以说 bufio ,提供了一个缓冲区,读和写都先在缓冲区中,最后再一次性读取或者写入到文件里,降低访问本地磁盘的次数。
一、bufio的基本概念和原理
bufio的主要作用是减少I/O操作的次数,提供读写性能。其工作原理是通过在内存中维护一个缓冲区,先将数据读入缓冲区,再从缓冲区中读取数据,从而减少对底层I/O设备的访问次数。
bufio的主要对象是缓冲区,操作主要有两个:读和写。读操作时,如果缓冲区为空,则从文件读取数据填满缓冲区;如果缓冲区不为空,则从缓冲区读取数据。写操作时,如果缓冲区未满,则将数据写入缓冲区;如果缓冲区已满,则将缓冲区的数据写入文件,并继续写入剩余的数据。
二、bufio的读操作
bufio的读操作主要通过bufio.Reader对象实现,它提供了多种读取数据的方法,如Read、ReadLine、ReadString等。
1. 使用bufio.Reader读取文件内容
下面是一个使用bufio.Reader读取文件内容的示例:
package main
import("bufio""fmt""io""os")funcmain(){// 打开文件
file, err := os.Open("example.txt")if err !=nil{
fmt.Println("read file err:", err)return}defer file.Close()// 使用defer关闭文件// 创建bufio.Reader对象。借助bufio来读取文件内容// func NewReader(rd io.Reader) *Reader
reader := bufio.NewReader(file)// 循环读取文件内容for{// 通过Read方法Read()读取文件//buf := make([]byte, 1024)//n, err := bufioReader.Read(buf)//fmt.Println("读取到了多少个字节:", n)//读取到的内容//fmt.Println("读取到的内容:",string(buf[:n]))//通过ReadString方法读取文件// func (b *Reader) ReadString(delim byte) (string, error)//参数是以什么作为分隔符。读取得到的是字符串//注意,最后一行后面要是没有换行符,读取不到
str, err := reader.ReadString('\n')// 读取字符串,以换行符为分隔符if err == io.EOF {// 判断文件是否结尾break}elseif err !=nil{// 判断错误,打印错误
fmt.Printf("read file failed, err:%v", err)break}//循环中逐行打印出读取的内容
fmt.Printf("read string SuccessFull: %s\n", str)// 打印读取的文件内容}}
在这个示例中,我们首先使用os.Open函数打开文件,然后创建一个bufio.Reader对象,通过循环调用ReadString方法读取文件内容,每次读取一行。当遇到文件结尾时,ReadString方法会返回一个io.EOF错误,我们据此退出循环。
2. 统计文件中字符、空格、数字和其他字符的数量
下面是一个统计文件中字符、空格、数字和其他字符数量的示例:
package main
import("bufio""fmt""io""os")// CharCount 定义结构体type CharCount struct{
ChCount int
NumCount int
SpaceCount int
OtherCount int}funcmain(){// 打开文件
file, err := os.Open("example.txt")if err !=nil{
fmt.Println("read file err:", err)return}defer file.Close()// 使用defer关闭文件// 创建bufio.Reader对象
reader := bufio.NewReader(file)var count CharCount
// 循环读取文件内容for{//str, err := reader.ReadString('\n') // 读取字符串,以换行符为分隔符
str,_, err := reader.ReadLine()// 按行读取,最后一行没有换行符也能读到if err == io.EOF {// 判断文件是否结尾break}if err !=nil{// 判断错误,打印错误
fmt.Printf("read file failed, err:%v", err)break}//runeArr := []rune(str) // 将字符串转为切片类型
runeArr := str // 将字符串转为切片类型
fmt.Println("得到的数据是",string(runeArr))for_, v :=range runeArr {// 循环读取数组switch{case v >='a'&& v <='z':// 判断是不是小写字母fallthroughcase v >='A'&& v <='Z':// 判断是不是大写字母
count.ChCount++case v ==' '|| v =='\t':// 判断是不是空格
count.SpaceCount++case v >='0'&& v <='9':// 判断是不是数字
count.NumCount++default:
count.OtherCount++}}}
fmt.Printf("char count:%d\n", count.ChCount)
fmt.Printf("num count:%d\n", count.NumCount)
fmt.Printf("space count:%d\n", count.SpaceCount)
fmt.Printf("other count:%d\n", count.OtherCount)}
3. 使用Scanner读取标准输入
下面是一个使用bufio.Scanner读取标准输入的示例:
package main
import("bufio""fmt""os")funcmain(){// 读取键盘的输入// 键盘的输入,实际上是流 os.Stdin
inputReader := bufio.NewReader(os.Stdin)// delim 到哪里结束读取 以换行符作为分隔符,之言不换行就可以一直读
readString,_:= inputReader.ReadString('\n')
fmt.Println("读取键盘输入的信息:", readString)}
三、bufio的写操作
bufio的写操作主要通过bufio.Writer对象实现,它提供了多种写入数据的方法,如Write、WriteString、Flush等。
1. 使用bufio.Writer写入文件内容
下面是一个使用bufio.Writer写入文件内容的示例:
package main
import("bufio""fmt""os")funcmain(){// 打开文件句柄,以写的方式打开,如果文件不存在则创建
file, err := os.OpenFile("F:\\goworks\\src\\jingtian\\yufa\\io操作\\bufio操作\\test_go_file.log",
os.O_CREATE|os.O_WRONLY,0644)if err !=nil{
fmt.Println("open file error:", err)return}defer file.Close()// 使用的defer语句关闭文件// 创建bufio.Writer对象
fileWrite := bufio.NewWriter(file)
inputStr :="Hello World ...\n"for i :=0; i <10; i++{// 循环写入数据
fileWrite.WriteString(inputStr)}// 发现并没有写出到文件,是留在了缓冲区,所以我们需要调用 flush 刷新缓冲区// 必须手动刷新才能写入进文件
fileWrite.Flush()// 刷新缓冲区,将数据写入文件}
在这个示例中,我们首先使用os.OpenFile函数打开文件,然后创建一个bufio.Writer对象,通过循环调用WriteString方法写入文件内容。最后,我们调用Flush方法刷新缓冲区,将数据写入文件。
2. 自定义io.Writer对象进行缓冲写
下面是一个自定义io.Writer对象进行缓冲写的示例:
package main
import("bufio""fmt""io""strings")// 自定义一个io.Writer对象type StringWriter struct{}func(s StringWriter)Write(p []byte)(n int, err error){// 这里简单地将数据写入一个字符串变量(实际使用时,可以将其写入内存、文件等)
fmt.Print(string(p))returnlen(p),nil}funcmain(){// 创建一个StringWriter对象
sw := StringWriter{}// 创建一个bufio.Writer对象,并传入StringWriter对象
writer := bufio.NewWriterSize(sw,10)// 写入数据
writer.WriteString("Hello, ")
writer.WriteString("world!\n")// 刷新缓冲区,将数据写入StringWriter对象
writer.Flush()}
在这个示例中,我们自定义了一个StringWriter对象,它实现了io.Writer接口的Write方法。然后,我们创建一个bufio.Writer对象,并传入StringWriter对象。接着,我们调用WriteString方法写入数据,并调用Flush方法刷新缓冲区,将数据写入StringWriter对象。
四、bufio的缓冲区大小
在bufio包中,Reader和Writer对象都有默认的缓冲区大小,但你也可以根据需要自定义缓冲区大小。
1. 默认缓冲区大小
对于
bufio.Reader
和
bufio.Writer
,Go语言标准库为它们提供了默认的缓冲区大小。对于
bufio.Reader
,默认缓冲区大小通常是4096字节(4KB);对于
bufio.Writer
,默认缓冲区大小也是4096字节(但在某些实现中可能略有不同,具体取决于底层操作系统的I/O性能)。
2. 自定义缓冲区大小
如果你需要更大的缓冲区来提高性能,或者更小的缓冲区来减少内存使用,你可以使用
bufio.NewReaderSize
和
bufio.NewWriterSize
函数来创建具有自定义缓冲区大小的Reader和Writer对象。
下面是一个自定义缓冲区大小的示例:
package main
import("bufio""fmt""os")funcmain(){// 打开文件
file, err := os.OpenFile("F:\\goworks\\src\\jingtian\\yufa\\io操作\\bufio操作\\custom_buffer_file.log", os.O_CREATE|os.O_WRONLY,0644)if err !=nil{
fmt.Println("open file error:", err)return}defer file.Close()// 使用defer语句关闭文件// 自定义缓冲区大小(例如:8KB)
bufferSize :=8*1024// 创建具有自定义缓冲区大小的bufio.Writer对象
fileWrite := bufio.NewWriterSize(file, bufferSize)
inputStr :="This is a line with custom buffer size.\n"for i :=0; i <10; i++{// 循环写入数据_, err := fileWrite.WriteString(inputStr)if err !=nil{
fmt.Println("write file error:", err)return}}// 刷新缓冲区,将数据写入文件
err = fileWrite.Flush()if err !=nil{
fmt.Println("flush buffer error:", err)return}
fmt.Println("Data written to file successfully with custom buffer size.")}
在这个示例中,我们创建了一个具有8KB缓冲区大小的
bufio.Writer
对象,并将其用于将数据写入文件。注意,在写入数据后,我们调用了
Flush
方法来确保缓冲区中的数据被写入文件。
对于
bufio.Reader
,你也可以使用类似的方法来创建具有自定义缓冲区大小的对象:
package main
import("bufio""fmt""os")funcmain(){// 打开文件
file, err := os.Open("F:\\goworks\\src\\jingtian\\yufa\\io操作\\bufio操作\\custom_buffer_file.log")if err !=nil{
fmt.Println("read file error:", err)return}defer file.Close()// 使用defer语句关闭文件// 自定义缓冲区大小(例如:8KB)
bufferSize :=8*1024// 创建具有自定义缓冲区大小的bufio.Reader对象
fileRead := bufio.NewReaderSize(file, bufferSize)// 读取文件内容(这里只是简单地读取并打印每一行)for{
line, err := fileRead.ReadString('\n')if err !=nil{if err.Error()=="EOF"{// 判断是否到达文件末尾break}
fmt.Println("read file error:", err)return}
fmt.Print(line)// 打印读取到的行}
fmt.Println("File read successfully with custom buffer size.")}
在这个示例中,我们创建了一个具有8KB缓冲区大小的
bufio.Reader
对象,并将其用于读取文件内容。注意,在处理文件读取时,我们需要检查错误是否为
EOF
(文件末尾),以确定是否应该退出循环。
通过自定义缓冲区大小,你可以根据具体的应用场景和需求来优化bufio的性能和内存使用。
版权归原作者 景天科技苑 所有, 如有侵权,请联系我们删除。