比如我们有一个 log 文件,运行了几年,有 100G 之大。按照我们之前的操作可能代码会这样写:
func ReadFile(filePath string) []byte { content, err := ioutil.ReadFile(filePath) if err != nil { log.Println("Read error") } return content }
上面的代码读取几兆的文件可以,但是如果大于你本身及其内存,那就直接翻车了。因为上面的代码,是把文件所有的内容全部都读取到内存之后返回,几兆的文件,你内存够大可以处理,但是一旦上几百兆的文件,就没那么好处理了。
那么,正确的方法有两种:
1. 使用流处理方式代码如下:
func ReadFile(filePath string, handle func(string)) error { f, err := os.Open(filePath) defer f.Close() if err != nil { return err } buf := bufio.NewReader(f) for { line, err := buf.ReadLine("n") line = strings.TrimSpace(line) handle(line) if err != nil { if err == io.EOF { return nil } return err } return nil } }
分片处理,当读取的是二进制文件,没有换行符的时候,使用下面的方案一样处理大文件
func ReadBigFile(fileName string, handle func([]byte)) error { f, err := os.Open(fileName) if err != nil { fmt.Println("can't opened this file") return err } defer f.Close() s := make([]byte, 4096) for { switch nr, err := f.Read(s[:]); true { case nr < 0: fmt.Fprintf(os.Stderr, "cat: error reading: %sn", err.Error()) os.Exit(1) case nr == 0: // EOF return nil case nr > 0: handle(s[0:nr]) } } return nil }