bufio详解

bufio包介绍

bufio包实现了有缓冲的I/O,它封装了一个io.Reader或io.Write接口对象,创建一个实现实现了该接口,同时提供缓冲和一些文本I/O的帮助函数.

bufio是通过缓存提高效率的

简单的说就是,把文件读取进缓冲(内存)之后再读取的时候就可以避免文件系统的io 从而提高速度。同理,在进行写操作时,先把文件写入缓冲(内存),然后由缓冲写入文件系统。看完以上解释有人可能会表示困惑了,直接把 内容->文件 和 内容->缓冲->文件相比, 缓冲区好像没有起到作用嘛。其实缓冲区的设计是为了存储多次的写入,最后一口气把缓冲区内容写入文件。下面会详细解释

bufio 封装了io.Reader或io.Writer接口对象,并创建另一个也实现了该接口的对象

io.Reader或io.Writer 接口实现read() 和 write() 方法,对于实现这个接口的对象都是可以使用这两个方法的

bufio实现原理

 

bufio源码分析

type Reader struct {
    		buf          []byte
    		rd           io.Reader // reader provided by the client
    		r, w         int       // buf read and write positions
    		err          error
    		lastByte     int
    		lastRuneSize int
    	}

//NewReaderSize将rd封装成了已给拥有size大小缓存的bufio.Reader对象

//如果rd的基类型就是bufio.Reader类型,而且拥有足够的缓存

//则直接返回rd的转换的基类型并返回

func NewReaderSize(rd io.Reader,size int)*Reader

//相当于NewReaderSize(rd, 4096)

func NewReader(rd io.Reader)*Reader

//Peek返回缓存的一个byte切片,该切片引用缓存中前n字节数据

//该操作不会读出数据,而是引用,因此可以改变缓存中的数据

//如果引用的数据长度小于n,则返回一个错误信息。

//如果n大于缓存的总大小,就返回ErrbufferFull

func (b *Reader) Peek(n int) ([]byte, error)

//当缓存区有内容的时,将缓存区内容全部填入p并清空缓存区

//当缓存区没有内容的时候且len(p)>len(buf),即要读取的内容比缓存区还要大

//直接去文件读取即可

//当缓存区没有内容的时候且len(p)<len(buf),即要读取的内容比缓存区小

//缓存区从文件读取内容充满缓存区,并将p填满(此时缓存区有剩余内容)

//以后再次读取时缓存区有内容,将缓存区内容全部填入p并清空缓存区(此时和情况1一样)

//无可读数据时,返回io.EOF

func (b *Reader) Read(p []byte) (n int, err error)


func ReadToBytes(rd io.Reader, b []byte) string {

	dataByte := make([]byte, 0)
	br := bufio.NewReader(rd)
	for {
		_, err := br.Read(b)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println(err.Error())
			return ""
		}
		dataByte = append(dataByte, b...)
	}
	return string(dataByte)
}

func (b *Reader) ReadSlice(delim byte) (line []byte, err error)

//ReadLine是一个低级的原始行读取操作。

//大多情况下,应该使用ReadBytes('n')或ReadString('\n')

/ ReadLine 通过调用 ReadSlice 方法实现,返回的也是缓存的切片
// ReadLine 尝试返回一个单行数据,不包括行尾标记(\n 或 \r\n)
// 如果在缓存中找不到行尾标记,则设置 isPrefix 为 true,表示查找未完成
// 同时读出缓存中的数据并作为切片返回
// 只有在当前缓存中找到行尾标记,才将 isPrefix 设置为 false,表示查找完成
// 可以多次调用 ReadLine 来读出一行
// 返回的数据在下一次读取操作之前是有效的
// 如果 ReadLine 无法获取任何数据,则返回一个错误信息(通常是 io.EOF)

func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)

// ReadString 功能同 ReadBytes,只不过返回的是一个字符串

func (b *Reader) ReadString(delim byte) (line string, err error)

func ReadToStrByDelim(rd io.Reader, delim byte) []string {

	dataSlice := make([]string, 0)
	br := bufio.NewReader(rd)
	if delim != '\n' {
		for {
			line := make([]byte, 0)
			line, err := br.ReadSlice(delim)
			if err == io.EOF {
				break
			}
			if err != nil {
				fmt.Println(err.Error())
				return nil
			}
			dataSlice = append(dataSlice, string(line))
		}
	} else {
		for {

			line, isPrefix, err := br.ReadLine()
			if err == io.EOF || isPrefix {
				break
			}
			if err != nil {
				fmt.Println(err.Error())
				return nil
			}
			dataSlice = append(dataSlice, string(line))
		}
	}

	return dataSlice
}

type Writer struct {

  err error

  buf []byte

  n  int

  wr io.Writer

}

//判断buf中的可用容量是否可以放下p

//如果可以放下,就把p拼接到buf后面,即把内容放到缓冲区

//如果buf中的可用容量不足以放下,并此时缓存区为空,就直接把p写到文件

//如果buf中的可用容量不足以放下,但此时缓冲区有内容,就用p把缓存区填满,并把缓存区

//所有内容写到文件,并清空缓冲区

//判断剩余内容的p可以放到缓冲区,如果可以放下,就放到缓冲区,否则就直接写入文件。

func (b *Writer) Write(p []byte) (nn int, err error)

//将缓冲区内容写到文件,当所有写入完成后,因为缓存区会存储内容,所以需要手动flush()到文件

func (b *Writer) Flush() error

//buf的可用容量,等于len(buf)-n

func (b *Writer)  Available() int
func WriteStr(w io.Writer, datas string) {
	writer := bufio.NewWriter(w)
	_, err := writer.WriteString(datas)
	if err != nil {
		fmt.Printf("WriteString failure,err: %v", err)
	}
	writer.Flush()
}

func WriteByte(w io.Writer, b []byte) {
	writer := bufio.NewWriter(w)
	_, err := writer.Write(b)
	if err != nil {
		fmt.Printf("WriteByte failure,err: %v", err)
	}
	writer.Flush()
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值