跳至主要內容

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
}
上次编辑于:
贡献者: ext.liyuanhao3