Golang解析CSV

Golang的csv库支持解析csv文件,导入encoding/csv就可以用了,但本身不太好用,特别是当CSV表列的顺序被打乱后,还得改动代码里面对应列在解析出的数据的索引,所以就这两个问题,简单封装了下,使之用起来更加方便,代码如下:

 1 package csvMgr
 2 
 3 import (
 4     "encoding/csv"
 5     "os"
 6     "strconv"
 7 
 8     "github.com/astaxie/beego"
 9 )
10 
11 type CsvTable struct {
12     FileName string
13     Records  []CsvRecord
14 }
15 
16 type CsvRecord struct {
17     Record map[string]string
18 }
19 
20 func (c *CsvRecord) GetInt(field string) int {
21     var r int
22     var err error
23     if r, err = strconv.Atoi(c.Record[field]); err != nil {
24         beego.Error(err)
25         panic(err)
26     }
27     return r
28 }
29 
30 func (c *CsvRecord) GetString(field string) string {
31     data, ok := c.Record[field]
32     if ok {
33         return data
34     } else {
35         beego.Warning("Get fileld failed! fileld:", field)
36         return ""
37     }
38 }
39 
40 func LoadCsvCfg(filename string, row int) *CsvTable {
41     file, err := os.Open(filename)
42     if err != nil {
43         beego.Error(err)
44         return nil
45     }
46     defer file.Close()
47 
48     reader := csv.NewReader(file)
49     if reader == nil {
50         beego.Error("NewReader return nil, file:", file)
51         return nil
52     }
53     records, err := reader.ReadAll()
54     if err != nil {
55         beego.Error(err)
56         return nil
57     }
58     if len(records) < row {
59         beego.Warning(filename, " is empty")
60         return nil
61     }
62     colNum := len(records[0])
63     recordNum := len(records)
64     var allRecords []CsvRecord
65     for i := row; i < recordNum; i++ {
66         record := &CsvRecord{make(map[string]string)}
67         for k := 0; k < colNum; k++ {
68             record.Record[records[0][k]] = records[i][k]
69         }
70         allRecords = append(allRecords, *record)
71     }
72     var result = &CsvTable{
73         filename,
74         allRecords,
75     }
76     return result
77 }

使用示例:

有一张Award表,结构如下:

定义一个结构体来表示这个配置表的一行数据

1 type AwardCfg struct {
2     Id   int
3     Type int
4     Val  int
5     Text string
6 }

使用上面的封装解析代码如下:

var g_allAwardCfg map[int]*AwardCfg

func LoadAwardCfg() bool {
    var result = LoadCsvCfg("csvmgr/award.csv", 2)
    if result == nil {
        return false
    }
    g_allAwardCfg = make(map[int]*AwardCfg)
    for _, record := range result.Records {
        id := record.GetInt("Id")
        aWard := &AwardCfg{
            id,
            record.GetInt("Type"),
            record.GetInt("Value"),
            record.GetString("Text"),
        }
        g_allAwardCfg[id] = aWard
    }
    return true
}

另外,用golang的CSV库解析CSV文件有特别注意一个问题,文档的格式一定要是不带BOM的UTF-8格式,不用UTF-8解析中文会乱码,带了BOM会导致第一个字段解析不出来。

 

posted on 2019-06-14 02:16  凄夜  阅读(7620)  评论(0编辑  收藏  举报

导航