Go 中的 encoding/csv 包:处理 CSV 文件的完整指南
CSV(逗号分隔值)格式仍然是交换表格数据最流行的方法之一。在 Go (Golang) 中,有一个标准包 encoding/csv 用于处理此格式,它提供了方便且高性能的接口来读取和写入 CSV 文件。在本文中,我们将详细介绍该包的所有功能,从基本操作到高级技术。
encoding/csv 包的主要功能
encoding/csv 包是 Go 标准库的一部分,无需安装额外的依赖项。它支持:
- 使用可配置的分隔符读取 CSV 文件
- 将数据写入 CSV 格式
- 处理引号和转义特殊字符
- 处理列标题
- 惰性读取(大文件的流式处理)
在 Go 中读取 CSV 文件
要读取 CSV 文件,使用 csv.Reader 结构体。考虑一个基本示例:
package main
import ( "encoding/csv" "fmt" "log" "os")
func main() { // 打开 CSV 文件 file, err := os.Open("data.csv") if err != nil { log.Fatal("打开文件错误:", err) } defer file.Close()
// 创建一个新的 CSV reader reader := csv.NewReader(file)
// 一次性读取所有记录 records, err := reader.ReadAll() if err != nil { log.Fatal("读取 CSV 错误:", err) }
// 输出数据 for i, record := range records { fmt.Printf("行 %d: %v", i+1, record) }}大文件的流式读取
为了处理大型 CSV 文件(数百兆字节或更多),建议逐行读取:
func readLargeCSV(filename string) error { file, err := os.Open(filename) if err != nil { return err } defer file.Close()
reader := csv.NewReader(file) // 跳过标题行 header, err := reader.Read() if err != nil { return err } fmt.Println("标题:", header)
// 逐行读取 lineCount := 0 for { record, err := reader.Read() if err != nil { break // 文件结束 } // 处理记录 fmt.Printf("行 %d: %s | %s", lineCount+1, record[0], record[1]) lineCount++ } return nil}配置 CSV 解析器
encoding/csv 包允许灵活配置读取参数:
Comma— 分隔符(默认为逗号)Comment— 注释字符(以此字符开头的行将被忽略)FieldsPerRecord— 每条记录中预期的字段数LazyQuotes— 允许未转义的引号TrimLeadingSpace— 删除字段开头的空格
func customCSVParser() { file, _ := os.Open("custom.csv") defer file.Close()
reader := csv.NewReader(file) reader.Comma = ';' // 使用分号 reader.Comment = '#' // 以 # 开头的行将被忽略 reader.TrimLeadingSpace = true reader.LazyQuotes = true
records, _ := reader.ReadAll() for _, record := range records { fmt.Println(record) }}将数据写入 CSV 格式
要写入数据,使用 csv.Writer 结构体。创建 CSV 文件的示例:
func writeCSV(filename string) error { file, err := os.Create(filename) if err != nil { return err } defer file.Close()
writer := csv.NewWriter(file) defer writer.Flush() // 重要!将缓冲区刷新到文件
// 写入标题