Go CSV - 读写 CSV
最后修改时间 2024 年 4 月 11 日
在本文中,我们将展示如何在 Golang 中读写 CSV 数据。
CSV
CSV(逗号分隔值)是一种非常流行的导入导出数据格式,用于电子表格和数据库。CSV 文件中的每一行都是一条数据记录。每条记录由一个或多个字段组成,字段之间用逗号分隔。虽然 CSV 是一种非常简单的数据格式,但可能存在许多差异,例如不同的分隔符、换行符或引用字符。
Golang 提供了 encoding/csv 包来处理 CSV。它提供了读写逗号分隔值(CSV)文件的函数。CSV 文件包含零个或多个记录,每条记录包含一个或多个字段。记录之间用换行符分隔。最后一条记录后面可以可选地跟着一个换行符。空格被视为字段的一部分。空行将被忽略。
Go CSV 读取
Read 函数从读取器中读取一条记录(字段切片)。
1,2,3,4,5 6,7,8,9,10
这是 numbers.csv 文件。
package main
import (
"encoding/csv"
"fmt"
"io"
"log"
"os"
)
func main() {
f, err := os.Open("numbers.csv")
if err != nil {
log.Fatal(err)
}
r := csv.NewReader(f)
for {
record, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
for value := range record {
fmt.Printf("%s\n", record[value])
}
}
}
在代码示例中,我们从 numbers.csv 文件读取值。
for {
record, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
for value := range record {
fmt.Printf("%s\n", record[value])
}
}
使用 Read 函数通过 for 循环逐行读取值。
$ go run read_fun.go 1 2 3 4 5 6 7 8 9 10
Go CSV 读取所有
ReadAll 函数从读取器中读取所有剩余的记录。每条记录都是一个字段切片。
first_name,last_name,occupation John,Doe,gardener Lucy,Smith,teacher Brian,Bethamy,programmer
这是 users.csv 文件。第一行是列名。
package main
import (
"encoding/csv"
"fmt"
"log"
"os"
)
type User struct {
firstName string
lastName string
occupation string
}
func main() {
records, err := readData("users.csv")
if err != nil {
log.Fatal(err)
}
for _, record := range records {
user := User{
firstName: record[0],
lastName: record[1],
occupation: record[2],
}
fmt.Printf("%s %s is a %s\n", user.firstName, user.lastName,
user.occupation)
}
}
func readData(fileName string) ([][]string, error) {
f, err := os.Open(fileName)
if err != nil {
return [][]string{}, err
}
defer f.Close()
r := csv.NewReader(f)
// skip first line
if _, err := r.Read(); err != nil {
return [][]string{}, err
}
records, err := r.ReadAll()
if err != nil {
return [][]string{}, err
}
return records, nil
}
该示例读取 users.csv 文件。每行都转换为 User 类型。
// skip first line
if _, err := r.Read(); err != nil {
return [][]string{}, err
}
这里我们跳过第一行,其中包含列名。
records, err := r.ReadAll()
我们使用 ReadAll 一次性获取所有记录。
$ go run read_all.go John Doe is a gardener Lucy Smith is a teacher Brian Bethamy is a programmer
Go CSV 不同分隔符
尽管名称为 CSV,但它可能包含逗号以外的其他分隔符。这是由于 CSV 格式缺乏标准化。
# this is users.csv file John;Doe;gardener Lucy;Smith;teacher Brian;Bethamy;programmer
在 users.csv 文件中,字段由分号分隔。该文件还包含一个注释。
package main
import (
"encoding/csv"
"fmt"
"log"
"os"
)
func main() {
f, err := os.Open("users.csv")
if err != nil {
log.Fatal(err)
}
r := csv.NewReader(f)
r.Comma = ';'
r.Comment = '#'
records, err := r.ReadAll()
if err != nil {
log.Fatal(err)
}
fmt.Print(records)
}
该示例从此文件读取所有数据。
r := csv.NewReader(f) r.Comma = ';' r.Comment = '#'
在这里,我们设置了分隔符和注释字符,以便包知道如何解析文件。
Go CSV 写入
Write 函数将单个 CSV 记录写入写入器。记录是一个字符串切片,每个字符串是一个字段。写入是缓冲的,因此必须调用 Flush 以确保记录已写入底层写入器。
package main
import (
"encoding/csv"
"log"
"os"
)
func main() {
records := [][]string{
{"first_name", "last_name", "occupation"},
{"John", "Doe", "gardener"},
{"Lucy", "Smith", "teacher"},
{"Brian", "Bethamy", "programmer"},
}
f, err := os.Create("users.csv")
defer f.Close()
if err != nil {
log.Fatalln("failed to open file", err)
}
w := csv.NewWriter(f)
defer w.Flush()
for _, record := range records {
if err := w.Write(record); err != nil {
log.Fatalln("error writing record to file", err)
}
}
}
在代码示例中,我们使用 Write 函数将几条记录写入 users.csv 文件。
Go CSV 写入所有
WriteAll 函数使用 Write 将多个 CSV 记录写入写入器,然后调用 Flush。
package main
import (
"encoding/csv"
"log"
"os"
)
func main() {
records := [][]string{
{"first_name", "last_name", "occupation"},
{"John", "Doe", "gardener"},
{"Lucy", "Smith", "teacher"},
{"Brian", "Bethamy", "programmer"},
}
f, err := os.Create("users.csv")
defer f.Close()
if err != nil {
log.Fatalln("failed to open file", err)
}
w := csv.NewWriter(f)
err = w.WriteAll(records) // calls Flush internally
if err != nil {
log.Fatal(err)
}
}
我们使用 WriteAll 一次性写入几条记录。
来源
在本文中,我们展示了如何在 Golang 中读写 CSV 数据。