前言

在Go中,输入和输出操作都是使用原语实现的,原语将数据模拟成可读的或者可写的字节流。
而Go的io包提供了io.Reader(将数据从某个资源读取到传输缓冲区被流式传输和使用)和io.Writer(从缓冲区读取数据,并写入目标资源)接口。

  • 实现了io.Reader接口的唯一方法Read(p []byte)(n int, err error),它就是一个读取器。

    • n 读取到的字节数
    • err 发生错误的信息(注意:资源读取完毕返回io.EOF错误)

      使用Reader

      思路: Reader方法内部是循环被调用的,每次迭代都会从数据源取一块数据放入缓冲区p,资源读取完毕返回io.EOF错误为止。
      我们通过strings.NewReader(string) 创建一个字符串读取器来迭代读取:

      package main
      
      import (
          "fmt"
          "io"
          "os"
          "strings"
      )
      
      func main() {
          //创建一个字符串读取器
          reader := strings.NewReader("How are you today You were in a bad mood yesterday")
          //创建一个长度为3的切片
          p := make([]byte, 3)
          //循环取数据
          for {
              //读取到的字节数,err 发生错误的信息(注意:资源读取完毕返回io.EOF错误)
              n, err := reader.Read(p)
              if err != nil {
                  if err == io.EOF {
                      fmt.Println("The resource is read!")
                      break
                  }
                  fmt.Println("Read err :", err.Error())
                  os.Exit(1)
              }
              fmt.Println(string(p[:n]), p[:n])
          }
      }

      输出打印的内容:

      How [72 111 119]
      ar [32 97 114]
      e y [101 32 121]
      ou [111 117 32]
      tod [116 111 100]
      ay [97 121 32]
      You [89 111 117]
      we [32 119 101]
      re [114 101 32]
      in [105 110 32]
      a b [97 32 98]
      ad [97 100 32]
      moo [109 111 111]
      d y [100 32 121]
      est [101 115 116]
      erd [101 114 100]
      ay [97 121]

      The resource is read!

      拓展例子(读取文件行数并且打印每一行内容和二进制流)

      package main
      
      import (
          "bufio"
          "fmt"
          "os"
          "time"
      )
      
      func main() {
          if len(os.Args) < 2 {
              os.Exit(1)
          }
          filename := os.Args[1]
          file, err := os.Open(filename)
          defer file.Close()
          if err != nil {
              fmt.Println(err.Error())
              os.Exit(1)
          }
      
          reader := bufio.NewReader(file)
          var line int
          fmt.Print("下面为你读取",filename,"每一行的内容:\n")
          for {
              lineContent, isPrefix, err := reader.ReadLine()
              if err != nil {
                  break
              }
              if !isPrefix {
                  line++
                  time.Sleep(time.Second*1)
                  fmt.Println("第",line,"行的二进制数据流为:", lineContent,"内容是:",string(lineContent))
                  fmt.Print("\n")
              }
          }
          fmt.Println("名字为:",filename,"的文件一共有:", line,"行")
      }
Last modification:September 25, 2020
如果觉得我的文章对你有用,请随意赞赏