您的位置:首页 > 编程语言 > Go语言

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

2017-04-15 00:34 771 查看
生命不止,继续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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: