Go jdk版本1.10.3 Scanner源码在bufio包中的scan.go文件中
一、Scanner介绍
Scanner提供一个按指定规则来读取数据的缓冲区IO,比如通过”行匹配函数”来逐行读取数据,Scanner通过Scan方法来按”匹配函数”读取数。
Scan方法会通过一个“匹配函数”读取数据中符合要求的部分,跳过不符合要求的部分。
“匹配函数”由调用者指定。本包中提供的匹配函数有"行匹配函数"、"字节匹配函数"、"字符匹配函数"、"单词匹配函数",用户也可以自定义"匹配函数"。默认的匹配函数为"行匹配函数",用于获取数据中的一行内容(不包括行尾标记)。
Scanner使用了缓存,所以匹配部分的长度不能超出缓存的容量。默认缓存容量为bufio.MaxScanTokenSize,用户可以通过Buffer方法指定缓存及最大容量
Scan方法 在遇到下面的情况时会终止扫描并返回 false(扫描一旦终止,将无法再继续):
1、遇到 io.EOF
2、遇到读写错误
3、“匹配部分”的长度超过了缓存的长度
二、Scanner源码
结构体
type Scanner struct {
r io.Reader // The reader provided by the client. 由用户提供的io.Reader
split SplitFunc // The function to split the tokens. 用于拆分tokens的函数(匹配函数,默认是行匹配)
maxTokenSize int // Maximum size of a token; modified by tests. token的最大长度
token []byte // Last token returned by split. 记录最后一次Scan操作匹配到的数据
buf []byte // Buffer used as argument to split.
start int // First non-processed byte in buf. 记录缓冲区buf中第一个未处理(扫描过)的位置
end int // End of data in buf. 记录buf的结束位置
err error // Sticky error.
empties int // Count of successive empty tokens. 记录匹配到空数据的次数,如果超过指定maxConsecutiveEmptyReads次数,则会panic
scanCalled bool // Scan has been called; buffer is in use. 标记Scan方法是否已经调用过,如果已经调用过则置为true,说明buffer在正在使用。
done bool // Scan has finished. 标记是否已经扫描结束
}
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
SplitFunc用来定义"匹配函数"类型,data是缓存中的数据,atEOF标记数据是否读完。
advance返回data中已处理的数据的长度。token返回找到的"匹配部分"数据,"匹配部分"可以是缓存的切片,也可以是自己新建的数据(比如bufio.errorRune)。"匹配部分"将在Scan之后通过Bytes和Text反馈给用户。err返回错误信息
如果在 data 中无法找到一个完整的“匹配部分”则应返回 (0, nil, nil),以便告诉Scanner 向缓存中填充更多数据,然后再次扫描(Scan 会自动重新扫描)。如果缓存已经