bufio.Scanner
是 Go 标准库中的一个类型,用于高效地逐行读取输入,通常用于处理来自文件、标准输入或其他 I/O 源的流式数据。它的主要功能是将输入按行或自定义分隔符进行分割,便于逐行或逐段处理数据。下面是关于 bufio.Scanner
的简单介绍。
1. 基本用法
创建 Scanner
要使用 bufio.Scanner
,首先需要创建一个 Scanner
实例。通常,使用 bufio.NewScanner
函数将一个实现了 io.Reader
接口的对象作为参数传递给 NewScanner
。
file, err := os.Open("filename.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
上面的代码中,file
是一个实现了 io.Reader
接口的 *os.File
对象。
逐行扫描
创建 Scanner
实例后,可以使用 Scanner
的 Scan
方法逐行读取输入。每调用一次 Scan
,Scanner 会读取下一行的数据。
for scanner.Scan() {
line := scanner.Text() // 获取当前行的文本
fmt.Println(line)
}
Scan
方法会返回 false
,当到达输入的末尾或遇到错误时,结束循环。
错误处理
在扫描过程中,可以使用 Err
方法来检查是否发生了错误。
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
2. 自定义分隔符
默认情况下,Scanner
使用换行符 (n
) 作为分隔符,将输入按行分割。但你可以通过 Split
方法自定义分隔符。
Go 提供了一些内置的分隔函数,例如:
bufio.ScanLines
:按行分割,这是默认的行为。bufio.ScanWords
:按单词分割。bufio.ScanRunes
:按 Unicode 字符分割。bufio.ScanBytes
:按字节分割。
你也可以实现自己的分隔函数,分隔函数的签名如下:
代码语言:go复制func(data []byte, atEOF bool) (advance int, token []byte, err error)
例如,如果你想按空格分割输入,可以使用:
代码语言:go复制scanner.Split(bufio.ScanWords)
3. 缓冲区大小
默认情况下,Scanner
使用的缓冲区大小为 64 KB。如果需要处理更大的单行输入,可以使用 Buffer
方法来调整缓冲区大小。
buf := make([]byte, 0, 1024*1024) // 1 MB
scanner.Buffer(buf, 1024*1024)
Buffer
方法的第一个参数是用作缓冲区的字节切片,第二个参数是缓冲区的最大大小。
4. 完整示例
下面是一个完整的示例,展示了如何使用 Scanner
逐行读取文件并处理每一行:
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
file, err := os.Open("filename.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
// 使用自定义分隔符,例如按空格分割
// scanner.Split(bufio.ScanWords)
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
5. 注意事项
Scanner
的缓冲区大小是有限的,如果行的长度超过缓冲区大小,默认情况下Scanner
会返回错误。对于超大输入,请考虑使用bufio.Reader
结合ReadLine
或者其他方式读取。Scanner
不适合处理需要一次性加载到内存中的非常大的输入数据,因为它只能按行或分隔符处理。
6. 小结
bufio.Scanner
提供了一种简单高效的方式来逐行读取数据,非常适合用于读取和处理文本文件或从标准输入读取命令行输入。在需要按行或按自定义分隔符读取输入时,bufio.Scanner
是一个非常有用的工具。