Go语言学习之bufio包(The way to go)

生命不止,继续Go go go.

还记得吗,我们之前介绍过ioutil包,今天继续再介绍一下bufio包吧。

从字面就看出来了,有buf,那就是缓冲的意思。

Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer object, creating another object (Reader or Writer) that also implements the interface but provides buffering and some help for textual I/O.

bufio 包实现了缓存IO。它包装了 io.Reader 和 io.Writer 对象,创建了另外的Reader和Writer对象,它们也实现了io.Reader和io.Writer接口,不过它们是有缓存的。该包同时为文本I/O提供了一些便利操作。

Reader 类型和方法

Reader结构

type Reader struct {
    buf          []byte     // 缓存
    rd           io.Reader  // 底层的io.Reader
    r, w         int
    err          error      // 读过程中遇到的错误
    lastByte     int        // 最后一次读到的字节
    lastRuneSize int        // 最后一次读到的Rune的大小
}

NewReaderSize

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

作用:
NewReaderSize 将 rd 封装成一个带缓存的 bufio.Reader 对象,
缓存大小由 size 指定(如果小于 16 则会被设置为 16)。
如果 rd 的基类型就是有足够缓存的 bufio.Reader 类型,则直接将
rd 转换为基类型返回。

NewReader

func NewReader(rd io.Reader) *Reader

NewReader 相当于 NewReaderSize(rd, 4096)

Peek

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

Peek 返回缓存的一个切片,该切片引用缓存中前 n 个字节的数据,
该操作不会将数据读出,只是引用,引用的数据在下一次读取操作之
前是有效的。如果切片长度小于 n,则返回一个错误信息说明原因。
如果 n 大于缓存的总大小,则返回 ErrBufferFull。

应用
新建一个file文件,输入wangshubo1989

package main

import (
    "bufio"
    "fmt"
    "os"
)


func main() {

    f, _ := os.Open("file")


    r4 := bufio.NewReader(f)
    b4, _ := r4.Peek(5)

    fmt.Printf("5 bytes: %s\n", string(b4))

    f.Close()

}

输出:wangs
Read

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

Read 从 b 中读出数据到 p 中,返回读出的字节数和遇到的错误。
如果缓存不为空,则只能读出缓存中的数据,不会从底层 io.Reader
中提取数据,如果缓存为空,则:
1、len(p) >= 缓存大小,则跳过缓存,直接从底层 io.Reader 中读出到 p 中。
2、len(p) < 缓存大小,则先将数据从底层 io.Reader 中读取到缓存
中,再从缓存读取到 p 中。

Buffered

func (b *Reader) Buffered() int

Buffered 返回缓存中未读取的数据的长度。

Discard

func (b *Reader) Discard(n int) (discarded int, err error)

Discard 跳过后续的 n 个字节的数据,返回跳过的字节数。
如果结果小于 n,将返回错误信息。
如果 n 小于缓存中的数据长度,则不会从底层提取数据。

Writer 类型和方法

writer结构

type Writer struct {
    err error       // 写过程中遇到的错误
    buf []byte      // 缓存
    n   int         // 当前缓存中的字节数
    wr  io.Writer   // 底层的 io.Writer 对象
}

NewWriterSize

func NewWriterSize(wr io.Writer, size int) *Writer

NewWriterSize 将 wr 封装成一个带缓存的 bufio.Writer 对象,
缓存大小由 size 指定(如果小于 4096 则会被设置为 4096)。
如果 wr 的基类型就是有足够缓存的 bufio.Writer 类型,则直接将
wr 转换为基类型返回。

NewWriter

func NewWriter(wr io.Writer) *Writer

NewWriter 相当于 NewWriterSize(wr, 4096)

WriteString

func (b *Writer) WriteString(s string) (int, error)

WriteString 功能同 Write,只不过写入的是字符串

WriteRune

func (b *Writer) WriteRune(r rune) (size int, err error)

WriteRune 向 b 写入 r 的 UTF-8 编码,返回 r 的编码长度。

Flush

func (b *Writer) Flush() error

Flush 将缓存中的数据提交到底层的 io.Writer 中

Available

func (b *Writer) Available() int

Available 返回缓存中未使用的空间的长度

Buffered

func (b *Writer) Buffered() int

Buffered 返回缓存中未提交的数据的长度

Reset

func (b *Writer) Reset(w io.Writer)

Reset 将 b 的底层 Writer 重新指定为 w,同时丢弃缓存中的所有数据,复位
所有标记和错误信息。相当于创建了一个新的 bufio.Writer。

应用

// Writing files in Go follows similar patterns to the
// ones we saw earlier for reading.

package main

import (
    "bufio"
    "fmt"
    "io/ioutil"
    "os"
)

func check(e error) {
    if e != nil {
        panic(e)
    }
}

func main() {

    // To start, here's how to dump a string (or just
    // bytes) into a file.
    d1 := []byte("hello\ngo\n")
    err := ioutil.WriteFile("/tmp/dat1", d1, 0644)
    check(err)

    // For more granular writes, open a file for writing.
    f, err := os.Create("/tmp/dat2")
    check(err)

    // It's idiomatic to defer a `Close` immediately
    // after opening a file.
    defer f.Close()

    // You can `Write` byte slices as you'd expect.
    d2 := []byte{115, 111, 109, 101, 10}
    n2, err := f.Write(d2)
    check(err)
    fmt.Printf("wrote %d bytes\n", n2)

    // A `WriteString` is also available.
    n3, err := f.WriteString("writes\n")
    fmt.Printf("wrote %d bytes\n", n3)

    // Issue a `Sync` to flush writes to stable storage.
    f.Sync()

    // `bufio` provides buffered writers in addition
    // to the buffered readers we saw earlier.
    w := bufio.NewWriter(f)
    n4, err := w.WriteString("buffered\n")
    fmt.Printf("wrote %d bytes\n", n4)

    // Use `Flush` to ensure all buffered operations have
    // been applied to the underlying writer.
    w.Flush()

}

Scanner 类型和方法

这个应该算是go中的特色了吧,反正对于c++过来的人说挺特别的。

在 bufio 包中有多种方式获取文本输入,ReadBytes、ReadString 和独特的 ReadLine,对于简单的目的这些都有些过于复杂了。在 Go 1.1 中,添加了一个新类型,Scanner,以便更容易的处理如按行读取输入序列或空格分隔的词等,这类简单的任务。它终结了如输入一个很长的有问题的行这样的输入错误,并且提供了简单的默认行为:基于行的输入,每行都剔除分隔标识。

应用

// A _line filter_ is a common type of program that reads
// input on stdin, processes it, and then prints some
// derived result to stdout. `grep` and `sed` are common
// line filters.

// Here's an example line filter in Go that writes a
// capitalized version of all input text. You can use this
// pattern to write your own Go line filters.
package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

func main() {

    // Wrapping the unbuffered `os.Stdin` with a buffered
    // scanner gives us a convenient `Scan` method that
    // advances the scanner to the next token; which is
    // the next line in the default scanner.
    scanner := bufio.NewScanner(os.Stdin)

    for scanner.Scan() {
        // `Text` returns the current token, here the next line,
        // from the input.
        ucl := strings.ToUpper(scanner.Text())

        // Write out the uppercased line.
        fmt.Println(ucl)
    }

    // Check for errors during `Scan`. End of file is
    // expected and not reported by `Scan` as an error.
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "error:", err)
        os.Exit(1)
    }
}

运行结果:
wangshubo1989
WANGSHUBO1989

你可能感兴趣的:(go,Go从入门到不放弃)