go语言操作csv
简介
本文讲解如何使用go语言读csv,如何使用go语言写csv文件,最后讲解一个内容如何使用使用go语言快速导出一个包含20万条记录的csv文件。
详细步骤
写csv
- 程序
package main
import (
"encoding/csv"
"os"
)
func main() {
//创建csv文件
f, err := os.Create("test.csv")
if err != nil {
panic(err)
}
//异步管理
defer f.Close()
// 写入UTF-8 BOM
f.WriteString("\xEF\xBB\xBF")
//创建一个新的写入文件流
w := csv.NewWriter(f)
data := [][]string{
{"序号", "姓名", "年龄","月薪"},
{"1", "小李", "23","2300"},
{"2", "小张", "23","2500"},
{"3", "小马", "23","5000"},
}
//写入数据
w.WriteAll(data)
w.Flush()
}
- 执行程序(
go run main.go
),完成后写入的csv文件
序号,姓名,年龄,月薪
1,"小李,",23,2300
2,小张,23,2500
3,小马,23,5000
读csv
package main
import (
"encoding/csv"
"fmt"
"io"
"log"
"os"
)
func main() {
//准备读取文件
fileName := "test.csv"
fs, err := os.Open(fileName)
if err != nil {
log.Fatalf("can not open the file, err is %+v", err)
}
defer fs.Close()
r := csv.NewReader(fs)
//针对大文件,一行一行的读取文件
for {
row, err := r.Read()
if err != nil && err != io.EOF {
log.Fatalf("can not read, err is %+v", err)
}
if err == io.EOF {
break
}
fmt.Println(row)
}
fmt.Println("\n---------------------------\n")
// 针对小文件,也可以一次性读取所有的文件。注意,r要重新赋值,因为readall是读取剩下的
fs1, _ := os.Open(fileName)
r1 := csv.NewReader(fs1)
content, err := r1.ReadAll()
if err != nil {
log.Fatalf("can not readall, err is %+v", err)
}
for _, row := range content {
fmt.Println(row)
}
}
- 执行程序(
go run main.go
),执行后输出入下日志:
[序号 姓名 年龄 月薪]
[1 小李, 23 2300]
[2 小张 23 2500]
[3 小马 23 5000]
---------------------------
[序号 姓名 年龄 月薪]
[1 小李, 23 2300]
[2 小张 23 2500]
[3 小马 23 5000]
快速导出文件
- 程序
package main
import (
"encoding/csv"
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
// 产生一个随机数
func RandInt(min, max int) int {
if min >= max || min == 0 || max == 0 {
return max
}
return rand.Intn(max-min) + min
}
func main() {
// 程序开始
fmt.Printf("csv demo started:%s\n", time.Now().Format("2006-01-02 15:05:02"))
//创建csv文件
f, err := os.Create("test.csv")
if err != nil {
panic(err)
}
//异步管理
defer f.Close()
// 写入UTF-8 BOM
f.WriteString("\xEF\xBB\xBF")
//创建一个新的写入文件流
w := csv.NewWriter(f)
// 定义内容长度
length := 300000
fmt.Printf("start create data: time=%v,len=%d\n",time.Now().Format("2006-01-02 15:05:02"),length)
data := make([][]string, length + 1 ) //创建第一维长度
for i := range data{
data[i]= make([]string,4) //创建第二维长度
}
// 填充第一行数据
data[0][0] = "序号"
data[0][1] = "姓名"
data[0][2] = "年龄"
data[0][3] = "月薪"
// 随机生成数据,实际工作中这部分数据应该从数据库内获取
for i:=0; i<length; i++ {
// 填充第2~N行数据
data[i+1][0] = strconv.Itoa(i)
data[i+1][1] = "姓名"+ strconv.Itoa(i)
data[i+1][2] = strconv.Itoa(RandInt(15,30))
data[i+1][3] = strconv.Itoa(RandInt(2000,5000))
}
fmt.Printf("create data success: time=%v,len=%d\n",time.Now().Format("2006-01-02 15:05:02"),length)
//写入数据
w.WriteAll(data)
w.Flush()
fmt.Printf("save data success: time=%v,len=%d\n",time.Now().Format("2006-01-02 15:05:02"),length)
}
- 发现执行时间很快,基本上1秒内完成了相关工作,在m级别的数据上,应该够用了
快速导出文件(大文件处理)
上一个章节,笔者把所有内容都加载到内存内,如果导出文件是一个很大的文件该方案可能会传OOM的情况。为解决该问题可修改成如下方案: