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

先看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. 22.Linux定时任务

    1.计划任务时间管理 参数 含义 -e 编辑定时任务 -l 查看定时任务 -r 删除定时任务 -u 指定其他用户 \* 表示任意的(分.时.日.月.周)时间都执行 \- 表示一个时间范围段, 如5-7 ...

  2. Redis学习四(运维指南).

    一.上线规划 一般 redis 的参数配置都在 redis.conf 中,在上线前根据实际环境配置好合适参数,能有效提高 redis 的可用性. redis 的运行机器 CPU 不求核数多,但求主频高 ...

  3. ESP8266开发之旅 网络篇⑧ SmartConfig——一键配网

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  4. jquery a标签的锚点点击的时候页面上缓慢滚动

    a标签增加一个名字触发效果: $(".transition").click(function(){ if (location.pathname.replace(/^\//, '') ...

  5. 数据结构(四十一)多路查找树(B树)

    一.多路查找树的背景 前面所讨论的查找算法都是在内存中进行的,它们适用于较小的文件,而对于较大的.存放在外存储器上的文件就不合适了,对于此类大规模的文件,即使是采用了平衡二叉树,在查找效率上仍然较低. ...

  6. unity 序列帧播放

    [SerializeField] private Image m_ScreenImage; //序列帧播放的image [SerializeField] ; // 一秒播放的帧数 [Serialize ...

  7. 【Leetcode 做题学算法周刊】第二期

    首发于微信公众号<前端成长记>,写于 2019.11.05 背景 本文记录刷题过程中的整个思考过程,以供参考.主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 20 ...

  8. Win10 连接CentOS 8 的Docker容器中 SqlServer数据库

    楔子 工作在win10环境下,使用Docker Windows桌面版容器化SqlServer数据库连接使用(主要是想用Docker),但是同时需要Linux系统测试,win10 下VMware 虚拟机 ...

  9. 【XSY1986】【BZOJ1455】罗马游戏

    就是一模板题. 合并就直接merge. pop就是将自己的值设为一,再将自己的左右儿子合并即可. 查询直接找到堆顶,输出. 模板左偏树 代码: #include<bits/stdc++.h> ...

  10. 记 Maven 本地仓库埋坑之依赖包为何不能用

    记一次 Maven 本地仓库埋坑之 Verifying Availability 背景 某 Java 后端项目使用 maven 构建,因为某些原因,某些依赖库下载不了,直接找其它人索要了他电脑上的 m ...