如何在Golang中实现文件流处理_边读边写大文件

Go处理大文件应采用流式处理,使用io.Copy实现高效边读边写,或用bufio.Scanner按行解析日志,避免OOM。

在 Go 中处理大文件时,直接读入内存会导致 OOM,正确做法是使用流式处理——边读边写,保持内存占用恒定。核心是利用 io.Copy 或带缓冲的 bufio 配合 os.File 的读写接口,避免一次性加载整个文件。

用 io.Copy 实现高效流式复制

io.Copy 是 Go 标准库中专为流式 I/O 设计的函数,内部自动使用 32KB 缓冲区,无需手动管理 buffer,适合大多数场景。

  • 打开源文件(只读)和目标文件(可写,建议用 os.O_CREATE | os.O_WRONLY | os.O_TRUNC
  • 直接调用 io.Copy(dst, src),它会持续从 src 读、向 dst 写,直到 EOF 或错误
  • 操作完成后记得关闭两个文件句柄

示例:

dst, _ := os.Create("output.txt")
src, _ := os.Open("input.log")
defer src.Close(); defer dst.Close()
io.Copy(dst, src) // 自动流式处理,内存友好

按行处理日志类文本(bufio.Scanner)

若需逐行解析(如过滤、转换、统计),bufio.Scannerbufio.Reader.ReadLine 更安全简洁,且默认限制每行 64KB,防止单行过大爆内存。

  • bufio.NewScanner(file) 包装文件对象
  • 循环调用 scanner.Scan(),每次 scanner.Text() 返回当前行(不含换行符)
  • 对每行做业务逻辑,再写入目标文件或输出到其他 IO 接口
  • 注意:若需处理超长行,可调 scanner.Buffer(make([]byte, 64*1024), 1

自定义缓冲读写(bufio.Reader/Writer)

当需要更精细控制(如跳过 BOM、校验、加解密、分块处理),可用 bufio.Readerbufio.Writer 手动读写。

  • 创建带缓冲的 reader/writer:r := bufio.NewReaderSize(f, 64*1024)w := bufio.NewWriterSize(out, 32*1024)
  • r.Read(p []byte)r.ReadBytes('\n') 等方式读取
  • 写入后别忘了 w.Flush(),否则内容可能滞留在缓冲区
  • 推荐设置缓冲大小为 4KB–64KB,太小增加系统调用开销,太大无益

错误处理与资源清理(关键!)

流式操作中,文件句柄、网络连接等资源必须显式释放,否则易泄漏。推荐用 defer + 明确 close,同时检查 close 错误(尤其写入后 close 可能触发磁盘 flush 错误)。

  • 打开文件后立即 defer close,但注意 defer 在函数 return 后才执行,要确保顺序合理
  • 写入完成后先 w.Flush(),再 w.Close(),并检查两者错误
  • 可封装工具函数统一处理 open/close/flush,减少重复代码

不复杂但容易忽略。