本文主要介绍go如何读取和写入csv文件,以及使用第三方库gocsv转换为Struct。
读取csv
go 标准库 “encoding/csv” 用于读写csv文件。
Reader从csv编码的文件中读取记录
- type Reader
- func NewReader(r io.Reader) *Reader
- func (r *Reader) Read() (record []string, err error) 。
- func (r *Reader) ReadAll() (records [][]string, err error)
创建一个csv文件servers.csv,具体如下
world-svc,1/1,Running,0,44m
battle-svc,1/1,Running,0,7d
ReadAll从r中读取所有剩余的记录,每个记录都是字段的切片,成功的调用返回值err为nil而不是EOF。因为ReadAll方法定义为读取直到文件结尾,因此它不会将文件结尾视为应该报告的错误。
package main
import (
"encoding/csv"
"fmt"
"io"
"os"
)
func main() {
readeCsvAll()
}
func readerCsvReadAll() {
file, err := os.Open("servers.csv")
defer file.Close()
if err != nil {
fmt.Println(err)
}
reader := csv.NewReader(file)
servers, _ := reader.ReadAll()
fmt.Println("ReadAll:", servers)
}
OutPut:
ReadAll: [world-svc 1/1 Running 0 44m] [battle-svc 1/1 Running 0 7d]]
Read从r读取一条记录,返回值record是字符串的切片,每个字符串代表一个字段。
reader := csv.NewReader(file)
for {
servers, err := reader.Read()
if err == io.EOF {
break
} else if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(servers)
}
输出和ReadAll是一样的。
csv读写逗号分隔值(csv)的文件,亦或可以定义数据的分隔符
reader.Comma = '|'
亦或可以定义忽略的的行
reader.Comment = '#'
写入csv
Writer类型的值将记录写入一个csv编码的文件
- type Writer
- func NewWriter(w io.Writer) *Writer
- func (w *Writer) Write(record []string) (err error)
- func (w *Writer) WriteAll(records [][]string) (err error)
- func (w *Writer) Flush()
- func (w *Writer) Error() error
向w中写入一条记录,会自行添加必需的引号。记录是字符串切片,每个字符串代表一个字段。
func writerOne() {
servers := []Server{
{"world-svc", "1/1", "Running", 0, "44m"},
{"battle-svc", "1/1", "Running", 0, "7d"},
}
file, err := os.Create("serversA.csv")
defer file.Close()
if err != nil {
log.Fatalln("failed to open file", err)
}
w := csv.NewWriter(file)
//将缓存中的数据写入底层的io.Writer。
defer w.Flush()
// 使用 Write
for _, server := range servers {
row := []string{server.Name, server.Ready, server.State, strconv.Itoa(server.Restarts), server.Age}
if err := w.Write(row); err != nil {
log.Fatalln("error writing server to file", err)
}
}
执行,在当前目录生成 serversA.csv,内容如下:
world-svc,1/1,Running,0,44m
battle-svc,1/1,Running,0,7d
WriteAll方法使用Write方法向w写入多条记录,并在最后调用Flush方法清空缓存
var data [][]string
for _, server := range servers {
row := []string{server.Name, server.Ready, server.State, strconv.Itoa(server.Restarts), server.Age}
data = append(data, row)
}
w.WriteAll(data)
To Struct
GoCSV包旨在提供 CSV 和 Go (golang) 值之间的快速和惯用的映射。 已有servers.csv 内容如下
Name,Ready,Status,Restart,Age
world-svc,1/1,Running,0,44m
battle-svc,1/1,Running,0,7d
UnmarshalFile(in *os.File, out interface{}) error UnmarshalFile从接口中的文件解析CSV。
func ToStruct() {
clientsFile, err := os.OpenFile("servers.csv", os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil {
panic(err)
}
defer clientsFile.Close()
var servers []*Server
//转换成 Server Object
if err := gocsv.UnmarshalFile(clientsFile, &servers); err != nil {
panic(err)
}
for _, server := range servers {
fmt.Println("Server", server.Name)
}
}
OuPut:
Server world-svc
Server battle-svc
更多api使用方式可参考:https ://github.com/gocarina/gocsv