Golang 中的 bufio 包是带缓冲 I/O 操作的标准库,之前的几篇文章详细讲解了 bufio.Reader、bufio.Writer 和 bufio.Scanner 这个几个结构体的使用方法、特性和使用场景,本文介绍一下 bufio 包中的函数。
介绍常用函数之前,先简单介绍下另一个结构体类型和一个函数类型:bufio.ReadWriter 和 bufio.SplitFunc,对应的定义如下:
type ReadWriter struct {
*Reader
*Writer
}
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
ReadWriter 结构体实现了 io.ReadWriter 接口,SplitFunc 是用来指定自定义分割规则的函数类型,通常结合 bufio.Scanner 使用。
创建对象函数
- func NewReader(rd io.Reader) *Reader,创建一个带缓冲的 Reader 对象。
- func NewWriter(w io.Writer) *Writer,创建一个带缓冲的 Writer 对象。
- func NewReadWriter(r *Reader, w *Writer) *ReadWriter,创建一个带缓冲的 ReadWriter 对象。
- func NewReaderSize(rd io.Reader, size int) *Reader,创建一个带缓冲的 Reader 对象,使用 size 指定缓冲区的最小值。
- func NewWriterSize(w io.Writer, size int) *Writer,创建一个带缓冲的 Writer 对象,使用 size 指定缓冲区的最小值。
- func NewScanner(r io.Reader) *Scanner,创建一个带缓冲的 Scanner 对象。
SplitFunc 类型函数
以下几个函数都是 SplitFunc 类型,通常与 bufio.NewScanner 一起使用。
- func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error),用于逐行读取输入流中的数据。
- func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error),用于逐个字节读取输入流中的数据。
- func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error),用于逐个 unicode 编码读取输入流中的数据。
- func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error),用于逐个单词(空格分割)读取输入流中的数据。
使用示例
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
// 确定读取文件的路径
path := "file.txt"
// 打开文件并处理错误
file, err := os.Open(path)
if err != nil {
panic(err)
}
defer file.Close()
// 创建Scanner类型对象
scanner := bufio.NewScanner(file)
// 设置分割函数
scanner.Split(bufio.ScanWords)
// 创建一个map对象,用于存储单词出现的次数
counts := make(map[string]int)
// 读取文件内容并统计单词出现次数
for scanner.Scan() {
word := strings.ToLower(scanner.Text())
counts[word]++
}
// 检查Scanner是否出错
if err := scanner.Err(); err != nil {
panic(err)
}
// 输出结果到控制台
for word, count := range counts {
fmt.Printf("%s: %dn", word, count)
}
// 让用户根据输入的关键字进行筛选
fmt.Print("Enter keyword to filter results: ")
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('n')
keyword := strings.TrimSpace(input)
if keyword != "" {
for word, count := range counts {
if strings.Contains(word, keyword) {
fmt.Printf("%s: %dn", word, count)
}
}
}
}
首先创建了一个 Scanner 类型的对象,指定了 ScanWords 作为分隔函数,然后遍历文件内容,统计单词出现的次数并将结果存储到一个map中,最后让用户输入关键字进行筛选,根据关键字过滤并输出结果。
小结
bufio 是一个提供了带缓冲读写操作的包,通过使用 bufio 包提供的类型和方法,可以高效地读写数据,特别是当涉及到大量数据的读写时,可以大大提高程序的性能。