bufio包
大约 2 分钟
bufio包
缓冲读
结构体
// 缓冲读
type Reader struct {
buf []byte
rd io.Reader // 提供的Reader实现(从现有的Reader转为带缓冲的)
r, w int // 缓冲区指针
err error
lastByte int // last byte read for UnreadByte; -1 means invalid
lastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}
创建缓冲读
const defaultBufSize = 4096 // 默认缓冲区容量
func NewReader(rd io.Reader) *Reader { return NewReaderSize(rd, defaultBufSize) }
const minReadBufferSize = 16
func NewReaderSize(rd io.Reader, size int) *Reader {
// 已经是缓冲读了并且缓冲区足够,直接返回
b, ok := rd.(*Reader)
if ok && len(b.buf) >= size {
return b
}
// 缓冲区最小是16字节
if size < minReadBufferSize {
size = minReadBufferSize
}
// 分配一个新的
r := new(Reader)
r.reset(make([]byte, size), rd)
return r
}
func (b *Reader) reset(buf []byte, r io.Reader) {
*b = Reader{
buf: buf,
rd: r,
lastByte: -1,
lastRuneSize: -1,
}
}
读
func (b *Reader) Read(p []byte) (n int, err error) {
n = len(p)
if n == 0 { // 没有分配缓冲区切片
// func (b *Reader) Buffered() int { return b.w - b.r } 可以读取的字节数
// 还有未读
if b.Buffered() > 0 {
return 0, nil
}
return 0, b.readErr()
}
if b.r == b.w { // 已经从内部缓冲区(b.buf)读完了
if b.err != nil {
return 0, b.readErr()
}
if len(p) >= len(b.buf) {
// 如果提供的切片足够大,直接读到提供的缓冲区切片.
// 避免一次拷贝(相对于下面的代码)
n, b.err = b.rd.Read(p) // 从原本的Reader直接读到缓冲区
if n < 0 {
panic(errNegativeRead)
}
if n > 0 {
b.lastByte = int(p[n-1])
b.lastRuneSize = -1
}
return n, b.readErr()
}
// 先读到内部的缓冲区,因为他比较大
// Do not use b.fill, which will loop.
b.r = 0
b.w = 0
n, b.err = b.rd.Read(b.buf)
if n < 0 {
panic(errNegativeRead)
}
if n == 0 {
return 0, b.readErr()
}
b.w += n
}
// 从内部的缓冲区,拷贝到提供的切片p中
// 读不完, 下次循环会直接走到这里接着读
// Note: if the slice panics here, it is probably because
// the underlying reader returned a bad count. See issue 49795.
n = copy(p, b.buf[b.r:b.w])
b.r += n
b.lastByte = int(b.buf[b.r-1])
b.lastRuneSize = -1
return n, nil
}
