加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

golang 中bufio包的用法

发布时间:2020-12-16 18:05:14 所属栏目:大数据 来源:网络整理
导读:本文转自GOlove博客:http://www.cnblogs.com/golove/p/3282667.html 并在此基础上进行了一些添加修改. bufio 包中的函数和方法 // bufio 包实现了带缓存的 I/O 操作 // 它封装一个 io.Reader 或 io.Writer 对象 // 使其具有缓存和一些文本读写功能 -------

本文转自GOlove博客:http://www.cnblogs.com/golove/p/3282667.html 并在此基础上进行了一些添加修改.

bufio 包中的函数和方法



// bufio 包实现了带缓存的 I/O 操作
// 它封装一个 io.Reader 或 io.Writer 对象
// 使其具有缓存和一些文本读写功能

------------------------------------------------------------

// bufio.go

------------------------------------------------------------

[html] view plain copy
  1. typeReaderstruct{
  2. buf[]byte
  3. rdio.Reader//readerprovidedbytheclient
  4. r,wint//bufreadandwritepositions
  5. errerror
  6. lastByteint
  7. lastRuneSizeint
  8. }

// NewReaderSize 将 rd 封装成一个拥有 size 大小缓存的 bufio.Reader 对象
// 如果 rd 的基类型就是 bufio.Reader 类型,而且拥有足够的缓存
// 则直接将 rd 转换为基类型并返回
func NewReaderSize(rd io.Reader,size int) *Reader

// NewReader 相当于 NewReaderSize(rd,4096)
func NewReader(rd io.Reader) *Reader
------------------------------------------------------------
// Peek 返回缓存的一个切片,该切片引用缓存中前 n 字节数据
// 该操作不会将数据读出,只是引用
// 引用的数据在下一次读取操作之前是有效的
// 如果引用的数据长度小于 n,则返回一个错误信息
// 如果 n 大于缓存的总大小,则返回 ErrBufferFull
// 通过 Peek 的返回值,可以修改缓存中的数据
// 但是不能修改底层 io.Reader 中的数据

[html] view plain copy

    funcmain(){
  1. s:=strings.NewReader("ABCDEFG")
  2. br:=bufio.NewReader(s)
  3. b,_:=br.Peek(5)
  4. fmt.Printf("%sn",b)
  5. //ABCDE
  6. b[0]='a'
  7. b,_=br.Peek(5)
  8. fmt.Printf("%sn",b)
  9. //aBCDE
  10. }

// Read 从 b 中读出数据到 p 中,返回读出的字节数
// 如果 p 的大小 >= 缓存的总大小,而且缓存不为空
// 则只能读出缓存中的数据,不会从底层 io.Reader 中提取数据
// 如果 p 的大小 >= 缓存的总大小,而且缓存为空
// 则直接从底层 io.Reader 向 p 中读出数据,不经过缓存
// 只有当 b 中无可读数据时,才返回 (0,io.EOF)
func (b *Reader) Read(p []byte) (n int,err error)
[html] view plain copy
    s:=strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
  1. b:=make([]byte,20)
  2. n,err:=br.Read(b)
  3. fmt.Printf("%-20s%-2v%vn",b[:n],n,err)
  4. //ABCDEFGHIJKLMNOPQRST20<nil>
  5. err=br.Read(b)
  6. //UVWXYZ123456789016 //0EOF
  7. // ReadByte 从 b 中读出一个字节并返回
    // 如果 b 中无可读数据,则返回一个错误
    func (b *Reader) ReadByte() (c byte,51); font-family:Arial; font-size:14px">// UnreadByte 撤消最后一次读出的字节
    // 只有最后读出的字节可以被撤消
    // 无论任何操作,只要有内容被读出,就可以用 UnreadByte 撤消一个字节
    func (b *Reader) UnreadByte() error
    [html] view plain copy
      c,_:=br.ReadByte()
    1. fmt.Printf("%cn",c)
    2. //A
    3. _=br.ReadByte()
    4. //B
    5. br.UnreadByte()
    6. c,_=br.ReadByte()
    7. fmt.Printf("%cn",c)
    8. //B
    9. // ReadRune 从 b 中读出一个 UTF8 编码的字符并返回
      // 同时返回该字符的 UTF8 编码长度
      // 如果 UTF8 序列无法解码出一个正确的 Unicode 字符
      // 则只读出 b 中的一个字节,并返回 U+FFFD 字符,size 返回 1
      func (b *Reader) ReadRune() (r rune,size int,51); font-family:Arial; font-size:14px">// UnreadRune 撤消最后一次读出的 Unicode 字符
      // 如果最后一次执行的不是 ReadRune 操作,则返回一个错误
      // 因此,UnreadRune 比 UnreadByte 更严格
      func (b *Reader) UnreadRune() error
      [html] view plain copy
        s:=strings.NewReader("你好,世界!")
      1. :=br.ReadRune()
      2. fmt.Printf("%c%vn",c,size)
      3. //你3
      4. _=br.ReadRune()
      5. //好3
      6. br.UnreadRune()
      7. _=br.ReadRune()
      8. fmt.Printf("%c%vn",size)
      9. //好3
      10. // Buffered 返回缓存中数据的长度
        [html] view plain copy
          func(b*Reader)Buffered()int
        1. funcmain(){
        2. fmt.Println(br.Buffered())
        3. //0
        4. br.Peek(1)
        5. //18
        6. // ReadSlice 在 b 中查找 delim 并返回 delim 及其之前的所有数据的切片
          // 该操作会读出数据,返回的切片是已读出数据的引用
          // 切片中的数据在下一次读取操作之前是有效的
          //
          // 如果 ReadSlice 在找到 delim 之前遇到错误
          // 则读出缓存中的所有数据并返回,同时返回遇到的错误(通常是 io.EOF)
          // 如果在整个缓存中都找不到 delim,则 err 返回 ErrBufferFull
          // 如果 ReadSlice 能找到 delim,则 err 始终返回 nil
          // 因为返回的切片中的数据有可能被下一次读写操作修改
          // 因此大多数操作应该使用 ReadBytes 或 ReadString,它们返回的不是数据引用
          func (b *Reader) ReadSlice(delim byte) (line []byte,220)"> [html] view plain copy
            s:=strings.NewReader("ABCDEFGHIJKL")
          1. w,_:=br.ReadSlice('')
          2. fmt.Printf("%qn",w)
          3. //"ABC"
          4. _=br.ReadSlice('')
          5. //"DEF"
          6. //"GHI"
          7. // ReadLine 是一个低级的原始的行读取操作
            // 大多数情况下,应该使用 ReadBytes('n') 或 ReadString('n')
            // 或者使用一个 Scanner
            // ReadLine 通过调用 ReadSlice 方法实现,返回的也是缓存的切片
            // ReadLine 尝试返回一个单行数据,不包括行尾标记(n 或 rn)
            // 如果在缓存中找不到行尾标记,则设置 isPrefix 为 true,表示查找未完成
            // 同时读出缓存中的数据并作为切片返回
            // 只有在当前缓存中找到行尾标记,才将 isPrefix 设置为 false,表示查找完成
            // 可以多次调用 ReadLine 来读出一行
            // 返回的数据在下一次读取操作之前是有效的
            // 如果 ReadLine 无法获取任何数据,则返回一个错误信息(通常是 io.EOF)
            func (b *Reader) ReadLine() (line []byte,isPrefix bool,220)"> [html] view plain copy
              s:=strings.NewReader("ABCnDEFrnGHIrnJKL")
            1. :=br.ReadLine()
            2. fmt.Printf("%q%vn",w,isPrefix)
            3. //"ABC"false
            4. _=br.ReadLine()
            5. //"DEF"false
            6. //"GHI"false
            7. // ReadBytes 在 b 中查找 delim 并读出 delim 及其之前的所有数据
              // 如果 ReadBytes 在找到 delim 之前遇到错误
              // 则返回遇到错误之前的所有数据,同时返回遇到的错误(通常是 io.EOF)
              // 只有当 ReadBytes 找不到 delim 时,err 才不为 nil
              // 对于简单的用途,使用 Scanner 可能更方便
              func (b *Reader) ReadBytes(delim byte) (line []byte,220)"> [html] view plain copy
                :=br.ReadBytes('')
              1. _=br.ReadBytes('')
              2. // ReadString 功能同 ReadBytes,只不过返回的是一个字符串
                func (b *Reader) ReadString(delim byte) (line string,220)"> [html] view plain copy
                  :=br.ReadString('')
                1. _=br.ReadString('')
                2. // WriteTo 实现了 io.WriterTo 接口
                  func (b *Reader) WriteTo(w io.Writer) (n int64,220)"> [html] view plain copy
                    s:=strings.NewReader("ABCEFG")
                  1. b:=bytes.NewBuffer(make([]byte,0))
                  2. br.WriteTo(b)
                  3. //ABCEFG
                  4. ------------------------------------------------------------

                    func (b *Reader) Reset(r io.Reader)
                    reset丢弃任何的缓存数据,丛植所有状态并且将缓存读切换到r

                    [html] view plain copy

                      packagemain
                    1. import(
                    2. "bufio"
                    3. "fmt"
                    4. "strings"
                    5. )
                    6. str:=strings.NewReader("123455")
                    7. br:=bufio.NewReader(s)
                    8. :=br.ReadString('n')
                    9. fmt.Println(b)//ABCEFG
                    10. br.Reset(str)
                    11. _=br.ReadString('n')
                    12. fmt.Println(b)//123455


                    13. ------------------------------------------------------------

                      // Writer 实现了带缓存的 io.Writer 对象
                      // 如果在向 Writer 中写入数据的过程中遇到错误
                      // 则 Writer 不会再接受任何数据
                      // 而且后续的写入操作都将返回错误信息
                      type Writer struct {

                         err   error
                       buf  []byte
                       n     int
                       wr   io.Writer
                      }
                      // NewWriterSize 将 wr 封装成一个拥有 size 大小缓存的 bufio.Writer 对象
                      // 如果 wr 的基类型就是 bufio.Writer 类型,而且拥有足够的缓存
                      // 则直接将 wr 转换为基类型并返回
                      func NewWriterSize(wr io.Writer,size int) *Writer
                      // NewWriter 相当于 NewWriterSize(wr,51); font-family:Arial; font-size:14px">func NewWriter(wr io.Writer) *Writer
                      // Flush 将缓存中的数据提交到底层的 io.Writer 中
                      func (b *Writer) Flush() error
                      // Available 返回缓存中的可以空间
                      func (b *Writer) Available() int
                      // Buffered 返回缓存中未提交的数据长度
                      func (b *Writer) Buffered() int
                      // Write 将 p 中的数据写入 b 中,返回写入的字节数
                      // 如果写入的字节数小于 p 的长度,则返回一个错误信息
                      func (b *Writer) Write(p []byte) (nn int,51); font-family:Arial; font-size:14px">// WriteString 同 Write,只不过写入的是字符串
                      func (b *Writer) WriteString(s string) (int,error)
                      [html] view plain copy
                        bw:=bufio.NewWriter(b)
                      1. fmt.Println(bw.Available())//4096
                      2. fmt.Println(bw.Buffered())//0
                      3. bw.WriteString("ABCDEFGH")
                      4. fmt.Println(bw.Available())//4088
                      5. fmt.Println(bw.Buffered())//8
                      6. bw.Flush()
                      7. fmt.Println(bw.Available())//4096
                      8. fmt.Println(bw.Buffered())//0
                      9. fmt.Printf("%qn",b)//"ABCEFG"
                      10. // WriteByte 向 b 中写入一个字节
                        func (b *Writer) WriteByte(c byte) error
                        // WriteRune 向 b 中写入 r 的 UTF8 编码
                        // 返回 r 的编码长度
                        func (b *Writer) WriteRune(r rune) (size int,220)"> [html] view plain copy
                          bw.WriteByte('H')
                        1. bw.WriteByte('e')
                        2. bw.WriteByte('l')
                        3. bw.WriteByte('l')
                        4. bw.WriteByte('o')
                        5. bw.WriteByte('')
                        6. bw.WriteRune('世')
                        7. bw.WriteRune('界')
                        8. bw.WriteRune('!')
                        9. bw.Flush()
                        10. fmt.Println(b)//Hello世界!
                        11. // ReadFrom 实现了 io.ReaderFrom 接口
                          func (b *Writer) ReadFrom(r io.Reader) (n int64,220)"> [html] view plain copy
                            s:=strings.NewReader("Hello世界!")
                          1. bw:=bufio.NewWriter(b)
                          2. bw.ReadFrom(s)
                          3. //bw.Flush()//ReadFrom无需使用Flush,其自己已经写入.
                          4. fmt.Println(b)//Hello世界!
                          5. func (b *Writer) Reset(w io.Writer) Reset丢弃任何没有写入的缓存数据,清除任何错误并且重新将b指定它的输出结果指向w

                            [html] view plain copy

                              "bytes"
                            1. "fmt"
                            2. bw.WriteString("123")
                            3. c:=bytes.NewBuffer(make([]byte,0))
                            4. bw.Reset(c)
                            5. bw.WriteString("456")
                            6. fmt.Println(b)//输出为空
                            7. fmt.Println(c)  //输出456


                            8. ------------------------------------------------------------

                              // ReadWriter 集成了 bufio.Reader 和 bufio.Writer
                              // 它实现了 io.ReadWriter 接口

                              [html] view plain copy
                                typeReadWriterstruct{
                              1. *Reader
                              2. *Writer
                              3. // NewReadWriter 封装 r 和 w 为一个 bufio.ReadWriter 对象
                                func NewReadWriter(r *Reader,w *Writer) *ReadWriter

                                [html] view plain copy

                                  "strings"
                                1. )
                                2. funcmain(){
                                3. b:=bytes.NewBuffer(make([]byte,108); list-style-type:decimal-leading-zero; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important; list-style-position:outside!important"> s:=strings.NewReader("123")
                                4. rw:=bufio.NewReadWriter(br,bw)
                                5. p,_:=rw.ReadString('n')
                                6. fmt.Println(string(p))//123
                                7. rw.WriteString("asdf")
                                8. rw.Flush()
                                9. fmt.Println(b)//asdf
                                10. // scan.go
                                  // Scanner 提供了一个方便的接口来读取数据,例如读取一个多行文本
                                  // 连续调用 Scan 方法将扫描数据中的“指定部分”,跳过各个“指定部分”之间的数据
                                  // Scanner 使用了缓存,所以“指定部分”的长度不能超出缓存的长度
                                  // Scanner 需要一个 SplitFunc 类型的“切分函数”来确定“指定部分”的格式
                                  // 本包中提供的“切分函数”有“行切分函数”、“字节切分函数”、“UTF8字符编码切分函数”
                                  // 和“单词切分函数”,用户也可以自定义“切分函数”
                                  // 默认的“切分函数”为“行切分函数”,用于获取数据中的一行数据(不包括行尾符)

                                  //
                                  // 扫描在遇到下面的情况时会停止:
                                  // 1、数据扫描完毕,遇到 io.EOF
                                  // 2、遇到读写错误
                                  // 3、“指定部分”的长度超过了缓存的长度
                                  // 如果要对数据进行更多的控制,比如的错误处理或扫描更大的“指定部分”或顺序扫描
                                  // 则应该使用 bufio.Reader

                                  type Scanner struct { r io.Reader // The reader provided by the client. split SplitFunc // The function to split the tokens. maxTokenSize int // Maximum size of a token; modified by tests. token []byte // Last token returned by split. buf []byte // Buffer used as argument to split. start int // First non-processed byte in buf. end int // End of data in buf. err error // Sticky error. }
                                  // SplitFunc 用来定义“切分函数”类型
                                  // data 是要扫描的数据
                                  // atEOF 标记底层 io.Reader 中的数据是否已经读完
                                  // advance 返回 data 中已处理的数据长度
                                  // token 返回找到的“指定部分”
                                  // err 返回错误信息
                                  // 如果在 data 中无法找到一个完整的“指定部分”
                                  // 则 SplitFunc 返回 (0,nil) 来告诉 Scanner
                                  // 向缓存中填充更多数据,然后再次扫描
                                  // 如果返回的 err 是非 nil 值,扫描将被终止,并返回错误信息
                                  // 如果 data 为空,则“切分函数”将不被调用
                                  // 意思是在 SplitFunc 中不必考虑 data 为空的情况
                                  // SplitFunc 的作用很简单,从 data 中找出你感兴趣的数据,然后返回
                                  // 并告诉调用者,data 中有多少数据你已经处理过了
                                  type SplitFunc func(data []byte,atEOF bool) (advance int,token []byte,51); font-family:Arial; font-size:14px">// NewScanner 创建一个 Scanner 来扫描 r
                                  // 默认切分函数为 ScanLines
                                  func NewScanner(r io.Reader) *Scanner
                                  // Err 返回扫描过程中遇到的非 EOF 错误
                                  // 供用户调用,以便获取错误信息
                                  func (s *Scanner) Err() error
                                  // Bytes 将最后一次扫描出的“指定部分”作为一个切片返回(引用传递)
                                  // 下一次的 Scan 操作会覆盖本次返回的结果
                                  func (s *Scanner) Bytes() []byte
                                  // Text 将最后一次扫描出的“指定部分”作为字符串返回(值传递)
                                  func (s *Scanner) Text() string
                                  // Scan 在 Scanner 的数据中扫描“指定部分”
                                  // 找到后,用户可以通过 Bytes 或 Text 方法来取出“指定部分”
                                  // 如果扫描过程中遇到错误,则终止扫描,并返回 false
                                  func (s *Scanner) Scan() bool
                                  [html] view plain copy

                                    s:=strings.NewReader("ABCnDEFrnGHInJKL")
                                  1. bs:=bufio.NewScanner(s)
                                  2. forbs.Scan(){
                                  3. fmt.Printf("%s%vn",bs.Bytes(),bs.Text())
                                  4. }
                                  5. //ABCABC
                                  6. //DEFDEF
                                  7. //GHIGHI
                                  8. //JKLJKL
                                  9. // Split 用于设置 Scanner 的“切分函数”
                                    // 这个函数必须在调用 Scan 前执行
                                    func (s *Scanner) Split(split SplitFunc)
                                    [html] view plain copy
                                      bs.Split(bufio.ScanWords)
                                    1. forbs.Scan(){
                                    2. fmt.Println(bs.Text())
                                    3. }
                                    4. //ABC
                                    5. //DEF
                                    6. //GHI
                                    7. //JKL
                                    8. // ScanBytes 是一个“切分函数”
                                      // 用来找出 data 中的单个字节并返回
                                      func ScanBytes(data []byte,220)"> [html] view plain copy
                                        s:=strings.NewReader("Hello世界!")
                                      1. bs.Split(bufio.ScanBytes)
                                      2. fmt.Printf("%s",bs.Text())
                                      3. // ScanRunes 是一个“切分函数”
                                        // 用来找出 data 中的单个 UTF8 字符的编码并返回
                                        // 如果 UTF8 解码出错,则返回的 U+FFFD 会被做为 "xefxbfxbd" 返回
                                        // 这使得用户无法区分“真正的U+FFFD字符”和“解码错误的返回值”
                                        func ScanRunes(data []byte,220)"> [html] view plain copy
                                          bs.Split(bufio.ScanRunes)
                                        1. }//Hello世界!
                                        2. }
                                        // ScanLines 是一个“切分函数”
                                        // 用来找出 data 中的单行数据并返回(包括空行)
                                        // 行尾标记可能是 n 或 rn(返回值不包括行尾标记)
                                        func ScanLines(data []byte,51); font-family:Arial; font-size:14px">// ScanWords 是一个“切分函数”
                                        // 用来找出 data 中的单词
                                        // 单词以空白字符分隔,空白字符由 unicode.IsSpace 定义
                                        func ScanWords(data []byte,err error)

                                        (编辑:李大同)

                                        【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读