-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcsv.go
90 lines (76 loc) · 1.44 KB
/
csv.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package mailmerger
import (
"encoding/csv"
"io"
"sync"
)
// Row represent a Row in csv
type Row struct {
mapHeaderIndex map[string]int
records []string
}
// GetCell get a cell value by a header key
func (r Row) GetCell(key string) (record string) {
idx, ok := r.mapHeaderIndex[key]
if !ok {
return
}
return r.records[idx]
}
// Map transform row into a map
func (r Row) Map() map[string]interface{} {
rmap := make(map[string]interface{}, len(r.records))
for header := range r.mapHeaderIndex {
rmap[header] = r.GetCell(header)
}
return rmap
}
// CSV a csv parser
type CSV struct {
mapHeaderIndex map[string]int
rows []Row
sync sync.Once
}
func (c *CSV) init() {
c.sync.Do(func() {
if c == nil {
c = &CSV{}
}
c.mapHeaderIndex = make(map[string]int)
})
}
// IsHeader check if the header is exists
func (c *CSV) IsHeader(header string) bool {
_, ok := c.mapHeaderIndex[header]
return ok
}
func (c *CSV) Parse(rd io.Reader) (err error) {
c.init()
cr := csv.NewReader(rd)
headers, err := cr.Read()
if err != nil {
return
}
for i, header := range headers {
if header == "" {
continue
}
c.mapHeaderIndex[header] = i
}
for {
records, err := cr.Read()
if err == io.EOF {
break
} else if err != nil {
return err
}
c.rows = append(c.rows, Row{
mapHeaderIndex: c.mapHeaderIndex,
records: records,
})
}
return nil
}
func (c *CSV) Rows() []Row {
return c.rows
}