CSV文件

CSV文件(Comma-Separated Values,也称为字符分隔值),是以纯文本形式存储表格数据(数字和文本)的文件;由任意条记录组成:

  • 记录间以换行符分隔;
  • 每条记录由多个字段组成,字段由分隔符(最常见的是逗号制表符)分割;
  • 字段包含特殊字符(逗号,换行符,或双引号),必须以双引号括住;

通常,所有记录都有完全相同的字段序列。

go读写

go中通过包"encoding/csv"可方便读写CSV文件

通过csv.NewReader可创建Reader,然后从文件中读取:

[]string[][]string
func readCsv(fileName string) {
    csvFile, err := os.Open(fileName)
    if err != nil {
        log.Println("Open CSV fail:", err)
    }
    defer csvFile.Close()

    csvReader := csv.NewReader(csvFile)
    for {
        row, err := csvReader.Read()
        if err != nil {
            if err != io.EOF {
                log.Println("Read CSV fail:", err)
            }
            break
        }

        log.Println("ROW: ", row)
    }

    //all, err := csvReader.ReadAll()
    //if err != nil {
    //	if err != io.EOF {
    //		log.Println("Read CSV fail:", err)
    //	}
    //}
    //log.Println("ALL:", all)    
}    

通过NewWriter写入(内容放在切片中)

func writeCSV(name string, contents [][]string) error {
    file, err := os.OpenFile(name, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
    if err != nil {
        log.Printf("Create CSV %v fail: %v", name, err)
        return err
    }
    defer file.Close()

    writer := csv.NewWriter(file)
    for _, line := range contents {
        writer.Write(line)
    }
    writer.Flush()

    return nil
}

YAML文件

YAML是一种数据序列化格式,方便人类阅读,且容易和脚本语言交互;格式与规则参见《[Python]读写YAML文件》

go中通过"gopkg.in/yaml.v3"可方便地进行YAML文件的读写。

读写接口

读取文件内容后,通过yaml.Unmarshal反序列化即可:

func readYaml[T any](fileName string) (*T, error) {
    data, err := ioutil.ReadFile(fileName)
    if err != nil {
        log.Printf("Read yaml fail: %v", err)
        return nil, err
    }

    conf := new(T)
    err = yaml.Unmarshal(data, conf)
    if err != nil {
        log.Printf("Unmarsh file %v to %T fail: %v", fileName, conf, err)
        return nil, err
    }
    return conf, nil
}

通过yaml.Marshal把结构序列化为YAML格式后,直接写入到文件即可:

func writeYaml[T any](fileName string, conf *T) error {
    data, err := yaml.Marshal(conf)
    if err != nil {
        log.Printf("Marshal conf %v fail: %v", conf, err)
        return err
    }

    err = ioutil.WriteFile(fileName, data, 0666)
    if err != nil {
        log.Printf("Write yaml fail: %v", err)
        return err
    }

    return nil
}

映射示例

以下YAML为例,在go中如何映射?

students:
  - mike:
      courses:
        - math
        - english
      class: 二年级一班
  - tom:
      courses:
        - math
        - history
      class: 二年级二班

students的子节点是学生(数组),而各个学生与其对应信息可用map存储;所以students就是一个map数组:

type studentData struct {
    Courses []string `yaml:"courses"`
    Class   string   `yaml:"class"`
}

type studentAll struct {
    Students []map[string]*studentData `yaml:"students"`
}