首页 > 编程笔记 > Go语言笔记 阅读:15

Go语言bufio包读写文件(非常详细)

Go 语言中的内置包 bufio 和 io/ioutil 有很多相似的功能,唯一的不同在于 bufio 提供了一些缓冲操作,如果对文件 I/O 操作(读写操作)比较频繁,使用 bufio 能提高读写性能。

bufio 定义了函数 NewReader()、NewReaderSize()、NewWriter() 和 NewWriterSize() 实现文件的读写操作,每个函数的说明如下:

函数 功能
NewReader(rd io.Reader) *Reader 通过工厂函数实例化结构体 Reader,主要实现文件读取操作。参数 rd 是文件对象,是由 os 包的 Open()、Create() 或 OpenFile() 打开文件生成的文件对象,返回值是已实例化的结构体 Reader。
NewReaderSize(rd io.Reader, size int) *Reader 与函数 NewReader() 的定义过程相同,参数 size 设置结构体 Reader 成员 buf 的数据长度,结构体成员 buf 是字节类型的切片,用于存放数据。
NewWriter(w io.Writer) *Writer 与函数 NewReader() 的定义过程相同,但它的功能主要是实现文件写入操作。
NewWriterSize(w io.Writer, size int) *Writer 与函数 NewReaderSize() 的定义过程相同,但它的功能主要是实现文件写入操作。

为什么定义函数 NewReader()、NewReaderSize()、NewWriter() 和 NewWriterSize()?

因为 NewReader() 和 NewWriter() 默认结构体成员 buf 的长度为 4096,如果数据长度大于 4096,只能使用 NewReaderSize() 和 NewWriterSize()。换句话说,NewReader(rd) 等同于 NewReaderSize(rd,4096),NewWriter(w) 等同于 NewWriterSize(w,4096)。

bufio 包的 NewReader() 和 NewReaderSize() 是返回已实例化的结构体 Reader,然后调用结构体方法就能实现文件的读取功能。

结构体 Reader 一共定义了 7 个方法读取文件:Read()、ReadByte()、ReadSlice()、ReadBytes()、ReadString()、ReadLine() 和 ReadRune(),每种方法在功能上都是大同小异,只是在数据类型上存在差异,以 ReadString() 为例进行介绍,示例如下:
package main

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

func main() {
   // 使用os创建或打开文件对象
   f, _ := os.OpenFile("output.txt", os.O_RDWR|os.O_SYNC, 0)
   // 实例化结构体Reader
   reader := bufio.NewReader(f)
   // 通过死循环方式读取每行数据
   for {
        // ReadString()按行读取数据
        buf, err := reader.ReadString('\n')
        // 输出当前读到的数据的长度
        fmt.Printf("当前数据长度:%v\n", len(buf))
        // 数据转换字符串格式,并去掉换行符
        value := strings.Trim(string(buf), "\r\n")
        // 如果数据不为空,则说明已读到数据
        if value != "" {
             fmt.Printf("当前数据:%v\n", value)
        } else {
             // 若数据为空,则可能是空行数据,但出现err说明已读取完成
             if err != nil {
                  break
             } else {
                  fmt.Printf("当前数据是空行数据\n")
             }
        }
   }
}
在 output.txt 文件中通过人为操作写入 3 行数据,第一行数据为 111,第二行数据为空,第三行数据为 222。运行上述代码,运行结果为:

当前数据长度:5
当前数据:111
当前数据长度:2
当前数据是空行数据
当前数据长度:3
当前数据:222
当前数据长度:0


上述示例适用于 ReadSlice()、ReadBytes() 或 ReadString(),只要在代码中修改结构体方法即可,将代码的reader.ReadString('\n')改为 ReadSlice() 或 ReadBytes(),程序的运行结果保持不变。

ReadSlice()、ReadBytes() 或 ReadString() 的参数 delim 是按照规则读取数据的,比如按行读取数据只要将参数 delim 设为 '\n' 即可。除 Read() 方法之外,其他方法都不能一次性读取文件的全部数据,它们非常适合按行读取或按某规律读取部分数能一次性读取文件的全部数据,它们非常适合按行读取或按某规律读取部分数据。

bufio 包的 NewWriter() 和 NewWriterSize() 是返回已实例化的结构体 Writer,然后调用结构体方法就能实现文件写入功能。

结构体 Writer 一共定义了 4 个方法写入文件:Write()、WriteByte()、WriteRune() 和 WriteString()。其中 WriteByte() 和 WriteRune() 将单个字节写入文件,使用频率较低;Write() 和 WriteString() 分别将字节切片和字符串写入文件。

接下来将演示 Write() 和 WriteString() 的使用,示例如下:
package main

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

func main() {
   // 使用os创建或打开文件对象
   f, _ := os.OpenFile("output.txt", os.O_RDWR|os.O_SYNC, 0)
   // 实例化结构体Writer
   reader := bufio.NewWriter(f)
   // 调用结构体方法Write()写入数据
   n1, _ := reader.Write([]byte("6666\n"))
   fmt.Printf("Write()已写入数据:%v\n", n1)
   // 调用结构体方法WriteString()写入数据
   n2, _ := reader.WriteString("7777\n")
   fmt.Printf("WriteString()已写入数据:%v\n", n2)
   // 调用结构体方法Flush()将数据保存到文件中
   reader.Flush()
}
运行上述代码,运行结果为:

Write()已写入数据:5
WriteString()已写入数据:5

结构体 NewWriter() 或 NewWriterSize() 写入数据的过程如下:
除此之外,bufio 包还定义了 NewReadWriter(r *Reader, w *Writer) *ReadWriter,它将 NewReader() 和 NewWriter() 的功能组合一起,使其同时具备文件读写功能。

相关文章