Post

大文件读写

大文件的读写操作要考虑到内存问题,一次性加载容易撑爆内存导致OOM

概念

  • 批处理系统(离线系统):系统接收一批数据,一段时间后(几分钟或几天)给用户返回结果。数据有明显的分界线,如一天、一周的数据量。一般用实时性要求不高的场景。
  • 流处理系统(准实时系统):实时性介于在线和批处理系统之间,系统接收到数据后,及时进行处理。数据量没有明显的分界点,该系统的延时也相对低一些

read handle

  • 分片处理:创建固定大小的buf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func BufHandle(filePath string, handleFun func([]byte)) error {
      f, err := os.Open(filePath)
      if err != nil {
          return err
      }
      defer f.Close()

      buf := make([]byte, 4096)
      for {
          n, err := f.Read(buf)
          if err != nil && err != io.EOF {
              return err
          }
          if err == io.EOF {
              return nil
          }

          handleFun(buf[:n])
      }
  }
  • 按行处理:读取一行,处理完成后读取下一行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func LineHandle(filePath string, handle func([]byte)) error {
      f, err := os.Open(filePath)
      defer f.Close()
      if err != nil {
          return err
      }

      buf := bufio.NewReader(f)

      for {
          line, isPrefix, err := buf.ReadLine()
          if err != nil && err != io.EOF {
              return err
          }
          if err == io.EOF {
              return nil
          }
          // 行太长,buf溢出
          if isPrefix {
              return errors.New("line too long")
          }

          handle(line)
      }
  }

write handle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func BufWrite() error {
    filePath := "./test.txt"
    file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
    if err != nil {
        return err
    }
    defer file.Close()

    write := bufio.NewWriter(file)
    for i := 0; i < 5; i++ {
        write.WriteString("http://c.biancheng.net/golang/ \n")
    }

    //Flush将缓存的文件真正写入到文件中
    write.Flush()

    return nil
}

总结

  • 文件的读写,采用缓冲区(内存)的方式效率更高,因为这样可以避免频繁的磁盘IO
  • write.Flush()是将缓冲区(内存)的数据写入磁盘

参考

  • bufio库:https://golang.org/pkg/bufio/
  • 详解golang中bufio包的实现原理:https://studygolang.com/articles/24343
This post is licensed under CC BY 4.0 by the author.