开放的编程资料库

当前位置:我爱分享网 > Go教程 > 正文

Golang中使用bufio包进行缓冲输入和输出

Gobufio教程展示了如何使用bufio包在Golang中进行缓冲输入和输出操作。

$ go version
go version go1.18.1 linux/amd64

我们使用Go版本1.18。

bufio包

内置的bufio包实现了缓冲IO操作。缓冲是一种提高IO操作性能的技术。

由于系统调用的成本很高,当我们将数据累积到缓冲区中进行读取或写入时,IO操作的性能会大大提高。这减少了所需的系统调用次数。

type Reader
type Writer
type Scanner

Reader为io.Reader对象实现缓冲。Writer为io.Writer对象实现缓冲。Scanner提供了一个方便的接口来读取数据,例如以换行符分隔的文本行文件。

使用bufio.NewReaderbufio.NewReaderSize创建了一个新的阅读器。

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

NewReader函数返回一个新的Reader,其缓冲区具有默认大小。NewReaderSize返回一个新的Reader,其缓冲区至少具有指定的大小。

使用bufio.NewWriterbufio.NewWriterSize创建了一个新的编写器。

func NewWriter(w io.Writer) *Writer
func NewWriterSize(w io.Writer, size int) *Writer

NewWriter函数返回一个新的Writer,其缓冲区具有默认大小。NewWriterSize返回一个新的Writer,其缓冲区至少具有指定的大小。

使用bufio.NewScanner创建了一个新的扫描器。

func NewScanner(r io.Reader) *Scanner

NewScanner返回一个新的Scanner以从r中读取。splitfunction默认为ScanLines

func (b *Writer) Flush() error

Flush将任何缓冲数据写入底层io.Writer。

GoReader.ReadString

ReadString一直读取到输入中第一次出现给定的定界符。

func (b *Reader) ReadString(delim byte) (string, error)

它返回一个包含数据的字符串,包括分隔符。

package main

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

func main() {

    fmt.Print("Enter your name: ")

    r := bufio.NewReader(os.Stdin)

    name, err := r.ReadString('\n')

    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Hello %s!\n", strings.TrimSpace(name))
}

使用ReadString函数,我们读取用户的输入并向控制台生成一条消息。

r := bufio.NewReader(os.Stdin)

我们从标准输入创建一个新的阅读器。

name, err := r.ReadString('\n')

从用户那里读取字符串输入。

$ go run main.go
Enter your name: Jan
Hello Jan!

GoWriter.WriteString

WriteString将字符串写入缓冲区。

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

它返回写入的字节数。

package main

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

func main() {

    data := []string{"an old falcon", "misty mountains",
        "a wise man", "a rainy morning"}

    f, err := os.Create("words.txt")

    if err != nil {
        log.Fatal(err)
    }

    defer f.Close()

    wr := bufio.NewWriter(f)

    for _, line := range data {

        wr.WriteString(line + "\n")
    }

    wr.Flush()

    fmt.Println("data written")
}

该示例使用Writer.WriteString将一些字符串写入文件。

wr := bufio.NewWriter(f)

创建了一个新的编写器。默认缓冲区大小为4KB。

for _, line := range data {

    wr.WriteString(line + "\n")
}

在for循环中,我们将数据写入缓冲区。

wr.Flush()

由于我们的数据小于默认的4KB缓冲区大小,我们必须调用Flush才能将数据实际写入文件。

用Scanner逐行读取文件

在下一个示例中,我们使用Scanner逐行读取文件。

sky
nice
cup
cloud
forest
water
pond
lake
snow

这是words.txt文件。

package main

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

func main() {

    f, err := os.Open("words.txt")

    if err != nil {
        log.Fatal(err)
    }

    defer f.Close()

    scanner := bufio.NewScanner(f)

    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}

该示例读取一个小文件,每行包含单词。

scanner := bufio.NewScanner(f)

使用bufio.NewScanner创建了一个新的扫描器。

for scanner.Scan() {
    fmt.Println(scanner.Text())
}

Scan函数将扫描器推进到下一个令牌,然后可以通过BytesText方法获得。默认情况下,函数按行前进。

$ go run main.go
sky
nice
cup
cloud
forest
water
pond
lake
snow

从字符串中读取单词

在下面的示例中,我们使用Scanner从字符串中读取单词。

package main

import (
    "bufio"
    "fmt"
    "log"
    "strings"
)

func main() {

    words := []string{}

    data := "A foggy mountain.\nAn old falcon.\nA wise man."

    sc := bufio.NewScanner(strings.NewReader(data))

    sc.Split(bufio.ScanWords)

    n := 0

    for sc.Scan() {
        words = append(words, sc.Text())
        n++
    }

    if err := sc.Err(); err != nil {
        log.Fatal(err)
    }

    fmt.Printf("# of words: %d\n", n)

    for _, word := range words {

        fmt.Println(word)
    }
}

strings.NewReader从字符串中返回一个新的阅读器。

sc.Split(bufio.ScanWords)

我们使用Split告诉扫描仪按单词扫描。

GoWriter.WriteRune

WriteRune写入单个符文。

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

它返回写入的字节数和任何错误。

package main

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

func main() {

    runes := "🐜🐬🐄🐘🦂🐫🐑🦍🐯🐞"

    f, err := os.Create("runes.txt")

    if err != nil {
        log.Fatal(err)
    }

    defer f.Close()

    wr := bufio.NewWriter(f)

    for _, _rune := range runes {

        wr.WriteRune(_rune)
        wr.WriteRune('\n')
    }

    wr.Flush()

    fmt.Println("runes written")
}

在示例中,我们从字符串中读取符文并将它们写入文件;每一个在一个单独的行上。

GoReader.Read

Reader.Read函数将数据读入一片字节。

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

它返回读取的字节数。

在下一个例子中我们同样使用了hex包,它实现了十六进制的编解码。

package main

import (
    "bufio"
    "encoding/hex"
    "fmt"
    "log"
    "os"
    "io"
)

func main() {

    f, err := os.Open("sid.jpg")

    if err != nil {
        log.Fatal(err)
    }

    defer f.Close()

    reader := bufio.NewReader(f)
    buf := make([]byte, 256)

    for {
        _, err := reader.Read(buf)

        if err != nil {

            if err != io.EOF {
                fmt.Println(err)
            }

            break
        }

        fmt.Printf("%s", hex.Dump(buf))
    }
}

在代码示例中,我们读取图像并以十六进制格式打印它。

reader := bufio.NewReader(f)

我们使用bufio.NewReader创建一个阅读器。

buf := make([]byte, 256)

我们创建了一个256字节的自定义缓冲区。

for {
    _, err := reader.Read(buf)
...

我们在for循环中读取二进制数据。

fmt.Printf("%s", hex.Dump(buf))

Dump返回一个字符串,其中包含给定数据的十六进制转储。

$ go run main.go
00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 00 00 01  |......JFIF......|
00000010  00 01 00 00 ff e1 00 2f  45 78 69 66 00 00 49 49  |......./Exif..II|
00000020  2a 00 08 00 00 00 01 00  0e 01 02 00 0d 00 00 00  |*...............|
00000030  1a 00 00 00 00 00 00 00  6b 69 6e 6f 70 6f 69 73  |........kinopois|
00000040  6b 2e 72 75 00 ff fe 00  3b 43 52 45 41 54 4f 52  |k.ru....;CREATOR|
00000050  3a 20 67 64 2d 6a 70 65  67 20 76 31 2e 30 20 28  |: gd-jpeg v1.0 (|
00000060  75 73 69 6e 67 20 49 4a  47 20 4a 50 45 47 20 76  |using IJG JPEG v|
00000070  38 30 29 2c 20 71 75 61  6c 69 74 79 20 3d 20 39  |80), quality = 9|
00000080  31 0a ff db 00 43 00 03  02 02 03 02 02 03 03 02  |1....C..........|
00000090  03 03 03 03 03 04 07 05  04 04 04 04 09 06 07 05  |................|
000000a0  07 0a 09 0b 0b 0a 09 0a  0a 0c 0d 11 0e 0c 0c 10  |................|
000000b0  0c 0a 0a 0e 14 0f 10 11  12 13 13 13 0b 0e 14 16  |................|
...

在本教程中,我们使用了Go中的bufio包。

列出所有Go教程。

未经允许不得转载:我爱分享网 » Golang中使用bufio包进行缓冲输入和输出

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏