本文是我有通俗的语言写的如果有误请指出。

先看bufio官方文档

https://studygolang.com/pkgdoc文档地址

主要分三部分Reader、Writer、Scanner

分别是读数据、写数据和扫描器三种数据类型的相关操作 这个扫描后面会详细说我开始也没弄明白其实很简单。


Reader

func NewReaderSize

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

NewReaderSize创建一个具有最少有size尺寸的缓冲、从r读取的*Reader。如果参数r已经是一个具有足够大缓冲的* Reader类型值,会返回r。

解释:看官方解释这个方法可能不太容易懂,这个意思就是就是你可以给*Reader自定义一个size大小的缓冲区,*Reader每次从底层io.Reader(也就是你那个文件或者流)中预读size大小的数据到缓冲区中(可能读不满),然后你每次读数据实际是从这个缓冲区中拿数据。

下面是NewReaderSize源码

func NewReaderSize(rd io.Reader, size int) *Reader {
// Is it already a Reader?
b, ok := rd.(*Reader)
if ok && len(b.buf) >= size {
return b
}
if size < minReadBufferSize { //minReadBufferSize==16
size = minReadBufferSize
}
r := new(Reader)
r.reset(make([]byte, size), rd)
return r
}

  r.reset 初始化了一个*Reader 返回大小是size。

func NewReader

func NewReader(rd io.Reader) *Reader

NewReader创建一个具有默认大小缓冲、从r读取的*Reader。

解释:那这个NewReader就很好解释了 和NewReaderSize基本一样就是缓冲区大小是默认设置好的

func (*Reader) Peek

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

解释:Peek就是返回缓存的一个切片,该切片引用缓存中的前N个字节的数据,如果n大于总大小,则返回能读到的字节数的数据。

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。

解释:如果缓存不为空则直接从缓存中读数据不会从底层io.Reader读,如果缓存为空len(p)>缓存大小,则直接从底层io.Reader读数据到p。

如果len(p)<缓存大小,则先从底层io.Reader中读数据到缓存再到p。

主要就这几个 还有几个文档写的都很清楚易懂我就不多写了。

Writer类型的方法和Reader类型的方法差不多也很易懂主要就一个Flush要注意。

func (*Writer) Flush

func (b *Writer) Flush() error

Flush方法将缓冲中的数据写入下层的io.Writer接口。

和Reader是倒过来的,Writer每次写数据是先写入缓冲区的,进程缓冲区填满后,通过进程缓冲写入到内核缓冲再写入到磁盘,使用Flush就不等填满直接走写入流程了,保证你的数据及时写入文件。


解释:scanner类型扫描器 官方的说法很复杂,我也没太看懂找了很多资料,其实就是你在数据传输的时候时候使用“分隔符”,scanner类型可以通过分隔符逐个迭代你的数据。

上面4个函数func Scan……  就是分隔符的判断函数这4个是给你预设好的,你也可以按照自己的需求改写。

怎么改写呢,看下面

func (*Scanner) Split

func (s *Scanner) Split(split SplitFunc)

这个Split方法就是设置你这个scanner的用哪个SplitFunc类型的函数

在看下面这个SpliFunc类型的函数签名

type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

照着这个格式写一个不就得了么,当然具体写法给出了但是你不会?没关系咱看一下官方是咋写的。

https://github.com/golang/go/blob/master/src/bufio/scan.go?name=release#57官方源码地址

func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
if i := bytes.IndexByte(data, '\n'); i >= 0 {
// We have a full newline-terminated line.
return i + 1, dropCR(data[0:i]), nil
}
// If we're at EOF, we have a final, non-terminated line. Return it.
if atEOF {
return len(data), dropCR(data), nil
}
// Request more data.
return 0, nil, nil
}

   

看bytes.IndexByte(data, '\n');这段不就是在找行尾嘛 比如你想改成以“;”为分隔符的就改成bytes.IndexByte(data, ';');不就得了么

func main(){
scanner:=bufio.NewScanner(
strings.NewReader("abcdefg\nhigklmn"),
)
scanner.Split(ScanLines) //这里可以随意选择用哪个函数也可以自定义,可以不指定默认为\n做分隔符
  for scanner.Scan(){
    fmt.Println(scanner.Text())
  }
}

  

到此为止拉~

标准库bufio个人详解的更多相关文章

  1. c/c++ 标准库 插入迭代器 详解

    标准库 插入迭代器 详解 插入迭代器作用:copy等函数不能改变容器的大小,所以有时copy先容器是个空的容器,如果不使用插入迭代器,是无法使用copy等函数的. 例如下面的代码就是错误的: list ...

  2. c/c++ 标准库 bind 函数 详解

    标准库 bind 函数 详解 bind函数:接收一个函数名作为参数,生成一个新的函数. auto newCallable = bind(callbale, arg_list); arg_list中的参 ...

  3. C++的iostream标准库介绍+使用详解(转)

    0 为什么需要iostream 我们从一开始就一直在利用C++的输入输出在做着各种练习,输入输出是由iostream库提供的,所以讨论此标准库是有必要的,它与C语言的 stdio库不同,它从一开始就是 ...

  4. C++标准库vector类型详解

    Vector简介 vector是定义在C++标准模板库,它是一个多功能.能够操作多种数据结构和算法的模板类(关于模板类我们后面会介绍,如何创建自己的模板类).vector是一个容器,能够像容器一样存放 ...

  5. 【Solr】索引库查询界面详解

    目录 索引库查询界面详解 回到顶部 索引库查询界面详解 q:主查询条件.完全支持lucene语法.还进行了扩展. fq:过滤查询.是在主查询条件查询结果的基础上进行过滤.例如:product_pric ...

  6. 全网最全的Windows下Python2 / Python3里正确下载安装用来向微信好友发送消息的itchat库(图文详解)

    不多说,直接上干货! 建议,你用Anaconda2或Anaconda3. 见 全网最全的Windows下Anaconda2 / Anaconda3里正确下载安装用来向微信好友发送消息的itchat库( ...

  7. python中requests库使用方法详解

    目录 python中requests库使用方法详解 官方文档 什么是Requests 安装Requests库 基本的GET请求 带参数的GET请求 解析json 添加headers 基本POST请求 ...

  8. 【Linux开发】Linux下jpeglib库的安装详解

    Linux下jpeglib库的安装详解 首先要下载所需的库压缩包:jpegsrc.v6b.tar.gz或 jpegsrc.v8b.tar.gz 然后将下载的压缩包随便放在和解压到你喜欢的地方. # t ...

  9. 常用开发库 - 告別BeanUtils拷贝,MapStruct工具库最全详解

    常用开发库 - MapStruct工具库详解 MapStruct是一款非常实用Java工具,主要用于解决对象之间的拷贝问题,比如PO/DTO/VO/QueryParam之间的转换问题.区别于BeanU ...

随机推荐

  1. Java Web 学习(1) —— Servlet

    Java Web 学习(1) —— Servlet 一. 什么是 Servlet Java Servlet 技术是Java体系中用于开发 Web 应用的底层技术. Servlet 是运行在 Servl ...

  2. Qt乱码的问题

    1.在启动应用程序前加入以下代码: //配置字符编码环境,让应用程序支持中文. QTextCodec *codec = QTextCodec::codecForName("System&qu ...

  3. Python 常见异常类型

    python标准异常 异常名称                                   描述 BaseException                         所有异常的基类Sy ...

  4. C++沉思录笔记 —— 序幕

    #include <stdio.h>   class Trace{public: void print(const char* s) { printf("%s\n", ...

  5. InitializingBean,spring 初始化bean

    springframework的提供接口,InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的 ...

  6. Android自定义控件:图形报表的实现(折线图、曲线图、动态曲线图)(View与SurfaceView分别实现图表控件)

    图形报表很常用,因为展示数据比较直观,常见的形式有很多,如:折线图.柱形图.饼图.雷达图.股票图.还有一些3D效果的图表等. Android中也有不少第三方图表库,但是很难兼容各种各样的需求. 如果第 ...

  7. VMware问题--无法获得 VMCI 驱动程序的版本: 句柄无效

    关于VMware问题:无法获得 VMCI 驱动程序的版本: 句柄无效.驱动程序“vmci.sys”的版本不正确 问题截图: 解决 1.根据配置文件路径找到对应的.vmx文件: 2.用编辑器打开,找到v ...

  8. 【原创】(十)Linux内存管理 - zoned page frame allocator - 5

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  9. Redis过期--淘汰机制的解析和内存占用过高的解决方案

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! Red ...

  10. MinIO 参数解析与限制

    MinIO 参数解析与限制 MinIO server 在默认情况下会将所有配置信息存到 ${HOME}/.minio/config.json 文件中. 以下部分提供每个字段的详细说明以及如何自定义它们 ...