Go语言自学系列 | golang标准库bufio
视频来源:B站《golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]》
一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:Go语言自学系列 | 汇总_COCOgsta的博客-CSDN博客_go语言自学
Bufio
bufio包实现了有缓冲的I/O。它包装一个io.Reader或io.Writer接口对象,创建另一个也实现了该接口,且同时还提供了缓冲和一些文本I/O的帮助函数的对象。
常量
const (defaultBufSize = 4096
)
变量
var (ErrInvalidUnreadByte = errors.New("bufio: invalid use of UnreadByte")ErrInvalidUnreadRune = errors.New("bufio: invalid uuse of UnreadRune")ErrBufferFull = errors.New("bufio: buffer full")ErrNegativeCouunt = errors.New("bufio: negative count")
)
var (ErrTooLong = errors.New("bufio.Scanner: token too long")ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count")ErrAdvanceTooFar = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input")
)
会被Scanner类型返回的错误。
type Reader
type Reader struct {buf []byterd io.Reader // reader provided by the clientr, w int // buf read and write positionserr errorlastByte int // last byte read for UnreadByte; -1 means invalidlastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}
Reader实现了给一个io.Reader接口对象附加缓冲
func NewReader
func NewReader(rd io.Reader) *Reader
NewReaderSize创建一个具有默认大小缓冲、从r读取的*Reader。NewReader相当于NewReaderSize(rd, 4096)
func NewReaderSize
func NewReaderSize(rd io.Reader, size int) *Reader
NewReaderSize创建一个具有最少有size尺寸的缓冲、从r读取的Reader。如果参数r已经是一个具有足够大缓冲的Reader类型值,会返回r。
func (*Reader) Reset(r.io.Reader)
func (b *Reader) Reset(r io.Reader)
Reset丢弃缓冲中的数据,清除任何错误,将b重设为其下层从r读取数据。
func main() {s := strings.NewReader("ABCDEFG")str := strings.NewReader("12345")br := bufio.NewReader(s)b, _ := br.ReadString('\n')fmt.Println(b)br.Reset(str)b, _ = br.ReadString('\n')fmt.Println(b)
}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
ABCDEFG
12345
func (*Reader) Read
func (b *Reader) Read(p []byte) (n int, err error)
Read读取数据写入p。本方法返回去写入p的字节数。本方法一次调用最多会调用下层Reader接口一次Read方法,因此返回值n可能小于len(p)。读取到达结尾时,返回值n将为0而err将为io.EOF。
func main() {s := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")br := bufio.NewReader(s)p := make([]byte, 10)for {n, err := br.Read(p)if err == io.EOF {break} else {fmt.Printf("string(p[0:n]): %v\n", string(p[0:n]))}}
}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
string(p[0:n]): ABCDEFGHIJ
string(p[0:n]): KLMNOPQRST
string(p[0:n]): UVWXYZ1234
string(p[0:n]): 567890
func (*Reader) ReadByte
func (b *Reader) ReadByte() (c byte, err error)
ReadByte读取并返回一个字节。如果没有可用的数据,会返回错误。
func (*Reader) UnreadByte
func (b *Reader) UnreadByte() error
UnreadByte吐出最近一次读取操作读取的最后一个字节。(只能吐出最后一个,多次调用会出问题)
func main() {s := strings.NewReader("ABCDEFG")br := bufio.NewReader(s)c, _ := br.ReadByte()fmt.Printf("%c\n", c)c, _ = br.ReadByte()fmt.Printf("%c\n", c)br.UnreadByte()c, _ = br.ReadByte()fmt.Printf("%c\n", c)
}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
A
B
B
func (*Reader) ReadRune
func (b *Reader) ReadRune() (r rune, size int, err error)
ReadRune读取一个utf-8编码的unicode码值,返回该码值、其编码长度和可能的错误。如果utf-8编码非法,读取位置只移动1字节,返回U+FFFD,返回值size为1而err为nil。如果没有可用的数据,会返回错误。
func (*Reader) UnreadRune
func (b *Reader) UnreadRune() error
UnreadRune吐出最后一次ReadRune调用读取的unicode码值。如果最近一次读取不是调用的ReadRune,会返回错误。(从这点看,UnreadRune比unreadByte严格很多)
func main() {s := strings.NewReader("你好,世界!")br := bufio.NewReader(s)c, size, _ := br.ReadRune()fmt.Printf("%c %v\n", c, size)c, size, _ = br.ReadRune()fmt.Printf("%c %v\n", c, size)br.UnreadRune()c, size, _ = br.ReadRune()fmt.Printf("%c %v\n", c, size)}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
你 3
好 3
好 3
func (*Reader) ReadLine
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
ReadLine尝试返回一行数据,不包括行尾标志的字节。如果行太长超过了缓冲,返回值isPrefix会被设为true,并返回行的前面一部分。该行剩下的部分将在之后的调用中返回。返回值isPrefix会在返回该行最后一个片段时才设为false。返回切片是缓冲的子切片,只在下一次读取操作之前有效。ReadLine要么返回一个非nil的line,要么返回一个非nil的err,两个返回值至少一个非nil。
返回的文本不包含行尾的标志字节(“\r\n”或"\n")。如果输入流结束时没有行尾标志字节,方法不会出错,也不会指出这一情况。在调用ReadLine之后调用UnreadByte会总是吐出最后一个读取的字节(很可能是该行的行尾标志字节),即使该字节不是ReadLine返回值的一部分。
func main() {s := strings.NewReader("ABC\nDEF\r\nGHI\r\nGHI")br := bufio.NewReader(s)w, isPrefix, _ := br.ReadLine()fmt.Printf("%q %v\n", w, isPrefix)w, isPrefix, _ = br.ReadLine()fmt.Printf("%q %v\n", w, isPrefix)w, isPrefix, _ = br.ReadLine()fmt.Printf("%q %v\n", w, isPrefix)w, isPrefix, _ = br.ReadLine()fmt.Printf("%q %v\n", w, isPrefix)}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
"ABC" false
"DEF" false
"GHI" false
"GHI" false
func (*Reader) ReadSlice
func (b *Reader) ReadSlice(delim byte) (line []byte, err error)
ReadSlice读取直到第一次遇到delim字节,返回缓冲里的包含已读取的数据和delim字节的切片。该返回值只在下一次读取操作之前合法。如果ReadSlice放在在读取到delim之前遇到了错误,它会返回在错误之前读取的数据在缓冲中的切片以及该错误(一般是io.EOF)。如果在读取delim之前缓冲就写满了,ReadSlice失败并返回ErrBufferFull。因为ReadSlice的返回值会被下一次I/O操作重写,调用者应尽量使用ReadBytes或ReadString替代本法功法。当且仅当ReadBytes方法返回的切片不以delim结尾时,会返回一次非nil的错误。
func main() {s := strings.NewReader("ABC,DEF,GHI,JKL")br := bufio.NewReader(s)w, _ := br.ReadSlice(',')fmt.Printf("%q\n", w)w, _ = br.ReadSlice(',')fmt.Printf("%q\n", w)w, _ = br.ReadSlice(',')fmt.Printf("%q\n", w)
}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
"ABC,"
"DEF,"
"GHI,"
func (*Reader) ReadString
func (b *Reader) ReadString(delim byte) (line string, err error)
ReadString读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的字符串。如果ReadString方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误(一般是io.EOF)。当且仅当ReadString方法返回的切片不以delim结尾时,会返回一个非nil的错误。
func main() {s := strings.NewReader("ABC DEF GHI JKL")br := bufio.NewReader(s)w, _ := br.ReadString(' ')fmt.Printf("%q\n", w)w, _ = br.ReadString(' ')fmt.Printf("%q\n", w)w, _ = br.ReadString(' ')fmt.Printf("%q\n", w)}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
"ABC "
"DEF "
"GHI "
func (*Reader) WriteTo
func (b *Reader) WriteTo(w io.Writer) (n int64, err error)
WriteTo方法实现了io.WriterTo接口。
func main() {s := strings.NewReader("ABCDEFGHIJKLMN")br := bufio.NewReader(s)b := bytes.NewBuffer(make([]byte, 0))br.WriteTo(b)fmt.Printf("%s\n", b)
}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
ABCDEFGHIJKLMN
type Writer
type Writer struct {err errorbuf []byten intwr io.Writer
}
Writer实现了为io.Writer接口对象提供缓冲。如果在向一个Writer类型值写入时遇到了错误,该对象将不再接受任何数据,且所有写操作都会返回该错误。在说有数据都写入后,调用者有义务调用Flush方法以保证所有的数据都交给了下层的io.Writer。
func NewWriter
func NewWriter(w io.Writer) *Writer
NewWriter创建一个具有默认大小缓冲、写入w的*Writer。NewWriter相当于NewWriterSize(wr, 4096)
func NewWriterSize
func NewWriterSize(w io.Writer, size int) *Writer
NewWriterSize创建一个具有最少有size尺寸的缓冲、写入w的Writer。如果参数w已经是一个具有足够大缓冲的Writer类型值,会返回w。
func (*Writer) Reset
func (b *Writer) Reset(w io.Writer)
Reset丢弃缓冲中的数据,清除任何错误,将b重设为将其输出写入w。
package mainimport ("bufio""bytes""fmt"
)func main() {b := bytes.NewBuffer(make([]byte, 0))bw := bufio.NewWriter(b)bw.WriteString("123456789")c := bytes.NewBuffer(make([]byte, 0))bw.Reset(c)bw.WriteString("456")bw.Flush()fmt.Println(b)fmt.Println(c)
}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"456
func (*Writer) Buffered
func (b *Writer) Buffered() int
Buffered返回缓冲中已使用的字节数。
func (*Writer) Available
func (b *Writer) Available() int
Available返回缓冲中海油多少字节未使用。
func (*Writer) Write
func (b *Writer) Write(p []byte) (nn int, err error)
Write将p的内容写入缓冲。返回写入的字节数。如果返回值nn < len(p),还会返回一个错误说明原因。
func (*Writer) WriteString
func (b *Writer) WriteString(s string) (int, error)
WriteString写入一个字符串。返回写入的字节数。如果返回值m < len(s),还会返回一个错误说明原因。
func (*Writer) WriteByte
func (b *Writer) WriteByte(c byte) error
WriteByte写入单个字节。
func (*Writer) WriterRune
func (b *Writer) WriteRune(r rune) (size int, err error)
WriteRune写入一个unicode码值(的utf-8编码),返回写入的字节数和可能的错误。
func (*Writer) Flush
func (b *Writer) Flush() error
Flush方法将缓冲中的数据写入下层的io.Writer接口。
func (*Writer) ReadFrom
func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)
ReadFrom实现了io.ReaderFrom接口。
package mainimport ("bufio""bytes""fmt"
)func main() {b := bytes.NewBuffer(make([]byte, 0))bw := bufio.NewWriter(b)fmt.Println(bw.Available()) // 4096fmt.Println(bw.Buffered()) // 0bw.WriteString("ABCDEFGHIJKLMN")fmt.Println(bw.Available())fmt.Println(bw.Buffered())fmt.Printf("%q\n", b)bw.Flush()fmt.Println(bw.Available())fmt.Println(bw.Buffered())fmt.Printf("%q\n", b)
}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
4096
0
4082
14
""
4096
0
"ABCDEFGHIJKLMN"
package mainimport ("bufio""bytes""fmt""strings"
)func main() {b := bytes.NewBuffer(make([]byte, 0))s := strings.NewReader("Hello 世界!")bw := bufio.NewWriter(b)bw.ReadFrom(s)// bw.Flush() // ReadFrom无需使用Flush,其自己已经写入fmt.Println(b) // Hello 世界!
}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
Hello 世界!
type ReadWriter
type ReadWriter struct {*Reader*Writer
}
ReadWriter类型保管了指向Reader和Writer类型的指针,(因此)实现了io.ReadWriter接口。
func NewReadWriter
func NewReadWriter(r *Reader, w *Writer) *ReadWriter
NewReadWriter申请创建一个新的、将读写操作分派给r和w的ReadWriter。
package mainimport ("bufio""bytes""fmt""strings"
)func main() {b := bytes.NewBuffer(make([]byte, 0))bw := bufio.NewWriter(b)s := strings.NewReader("123")br := bufio.NewReader(s)rw := bufio.NewReadWriter(br, bw)p, _ := rw.ReadString('\n')fmt.Println(string(p)) // 123rw.WriteString("asdf")rw.Flush()fmt.Println(b) // asdf
}
运行结果
[Running] go run "d:\SynologyDrive\软件开发\go\golang入门到项目实战\goproject\360duote.com\pro01\test.go"
123
asdf
type SplitFunc
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
SplitFunc类型代表用于对输出作词法分析的分割函数。
参数data是尚未处理的数据的一个开始部分的切片,参数atEOF表示是否Reader接口不能提供更多的数据。返回值是解析位置前进的字节数,将要返回给调用者的token切片,以及可能遇到的错误。如果数据不足以(保证)生成一个完整的token,例如需要一整行数据但data里没有换行符,SplitFunc可以返回(0, nil, nil)来告诉Scanner读取更多的数据写入切片然后用从同一位置起始、长度更长的切片再试一次(调用SplitFunc类型函数)。
如果返回值err非nil,扫描将终止并将该错误返回给Scanner的调用者。
除非atEOF为真,永远不会使用空切片data调用SplitFunc类型函数。然而,如果atEOF为真,data却可能是非空的、且包含着未处理的文本。
SplitFunc的作用很简单,从data中找出你感兴趣的数据,然后返回并告诉调用者,data中有多少数据你已经处理过了。
func ScanBytes
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)
ScanBytes是用于Scanner类型的分割函数(符合SplitFunc),本函数会将每个字节作为一个token返回。
func ScanRunes
func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)
ScanRunes是用于Scanner类型的分割函数(符合SplitFunc),本函数将每个utf-8编码的unicode码值作为一个token返回。本函数返回的rune序列和range一个字符串的输出rune序列相同。错误的utf-8编码会翻译为U+FFFD="\xef\xbf\xbd",但只会消耗一个字节。调用者无法区分正确编码的rune和错误编码的rune。
func ScanWords
func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)
ScanRunes是用于Scanner类型的分割函数(符合SplitFunc),本函数会将空白(参见unicode.IsSpace)分隔的片段(去掉前后空白后)作为一个token返回。本函数永远不会返回空字符串。用来找出data中的单行数据并返回(包括空行)
func ScanLines
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)
ScanLines是用于Scanner类型的分割函数(符合SplitFunc),本函数会将每一行文本去掉末尾的换行标记作为一个token返回。返回的行可以是空字符串。换行标记为一个可选的回车后跟一个必选的换行符。最后一行即使没有换行符也会作为一个token返回。
type Scanner
type Scanner struct {r io.Reader // The reader provided by the client.split SplitFunc // The function to split the token.maxTokenSize int // Maximum size of a token; modified by tests.token []byte // Last token returned by split.buf []byte // Buffer used an argument to split.start int // First non-processed byte in buf.end int // End of data in buf.err error // Sticky error.
}
Scanner类型提供了方便的读取数据的接口,如从换行符分隔的文本里读取每一行。成功调用的Scan方法会逐步提供文件的token,跳过token之间的字节。token由SplitFunc类型的分割函数指定;默认的分割函数会将输入分割为多个行,并去掉行尾的换行标志。本包预定义的分割函数可以将文件分割为行、字节、unicode码值、空白分隔的word。调用者可以定制自己的分割函数。扫描会在抵达输入流结尾、遇到的第一个I/O错误、token过大不能保存进缓冲时,不可恢复的停止。当扫描停止后,当前读取位置可能会在最后一个获得的token后面。需要更多对错误管理的控制或token很大,或必须从reader连续扫描的程序,应使用buffio.Reader代替。
func NewScanner
func NewScanner(r io.Reader) *Scanner
NewScanner创建并返回一个从r读取数据的Scanner,默认的分割函数时ScanLines。
func (*Scanner) Split
func (s *Scanner) Split(split SplitFunc)
Split设置该Scanner的分割函数。本方法必须在Scan之前调用。
package mainimport ("bufio""fmt""strings"
)func main() {s := strings.NewReader("ABC DEF GHI JKL")bs := bufio.NewScanner(s)bs.Split(bufio.ScanWords)for bs.Scan() {fmt.Println(bs.Text())}}
运行结果
[Running] go run "/Users/guoliang/SynologyDrive/软件开发/go/golang入门到项目实战/goproject/360duote.com/pro01/test.go"
ABC
DEF
GHI
JKL
func (*Scanner) Scan
func (s *Scanner) Scan() bool
Scan方法获取当前位置的token(该token可以通过Bytes或Text方法获得),并让Scanner的扫描位置移动到下一个token。当扫描因为抵达输入流结尾或者遇到错误而停止时,本方法会返回false。在Scan方法返回false后,Err方法将返回扫描时遇到的任何错误;除非是io.EOF,此时Err会返回nil。
package mainimport ("bufio""fmt""strings"
)func main() {s := strings.NewReader("Hello 世界!")bs := bufio.NewScanner(s)bs.Split(bufio.ScanBytes)for bs.Scan() {fmt.Printf("%s", bs.Text())}}
运行结果
[Running] go run "/Users/guoliang/SynologyDrive/软件开发/go/golang入门到项目实战/goproject/360duote.com/pro01/tempCodeRunnerFile.go"
Hello ��界!
func (*Scanner) Bytes
func (s *Scanner) Bytes() []byte
Bytes方法返回最近一次Scan调用生成的token。底层数组指向的数据可能会被下一次Scan的调用重写。
package mainimport ("bufio""fmt""strings"
)func main() {s := strings.NewReader("Hello 世界!")bs := bufio.NewScanner(s)bs.Split(bufio.ScanRunes)for bs.Scan() {fmt.Printf("%s", bs.Text())}}
运行结果
[Running] go run "/Users/guoliang/SynologyDrive/软件开发/go/golang入门到项目实战/goproject/360duote.com/pro01/tempCodeRunnerFile.go"
Hello 世界!
func (*Scanner) Text
func (s *Scanner) Text() string
Bytes方法返回最近一次Scan调用生成的token,会申请创建一个字符串保存token并返回该字符串。
func (*Scanner) Err
func (s *Scanner) Err() error
Err返回Scanner遇到的第一个非EOF的错误。
Go语言自学系列 | golang标准库bufio相关推荐
- Go语言自学系列 | golang标准库os模块 - 文件目录相关
视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,请移步至知乎网站,谢 ...
- Go语言自学系列 | golang标准库io包
视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...
- Go语言自学系列 | golang标准库log
视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...
- Go语言自学系列 | golang标准库os包进程相关操作
视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...
- Go语言自学系列 | golang标准库os模块 - File文件读操作
视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...
- Go语言自学系列 | golang标准库os包和环境相关的方法
视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...
- Go语言自学系列 | golang标准库bytes
视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...
- Go语言自学系列 | golang标准库errors
视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...
- Go语言自学系列 | golang简介
视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...
最新文章
- 5.13T1Send 题(send)
- WinForm 里面ListBox的问题
- euler‘s formula
- 22)PHP,数组排序函数
- SAP 3D visual enterprise viewer 9.0 的下载方式
- android 5.0.1 libdvm.so,Android逆向进阶—— 脱壳的奥义(基ART模式下的dump)
- LeetCode 2120. 执行所有后缀指令(模拟)
- 在python中创建虚拟环境和Django对数据库的操作(一)
- 跨境独立站必备!用 WhatsApp 玩转海外私域流量
- linux下python、django框架的配置
- 网络工程师_记录的一些真题_2017上半年上午
- lt18i android 2.3.4典藏版,索尼LT18i一键ROOT教程工具 2.3.4已亲测成功
- 快速实现微信公众号支付功能
- leetcode 5230 Check If It Is a Straight Line
- 这 5 本数据分析书籍,都是经典中的经典
- HAL库开发—基于stm32的智能小家电
- 实习生风采 · 贰 | 张倬胜同学:攻关「孟子」轻量化预训练模型
- 两个ip是否在同一网段?
- 迅为IMX6ULL开发板从零开始编译 buildroot
- 100条超搞笑的“雷人”QQ/MSN 签名