Golang Scanner分拆 自定义分隔的数据

我们经常会遇到解析某些自定义分隔的一串数列的问题。比如文章中的单词以空格分隔,csv格式或者临时由两种符号分隔的二维表数据。这些数据用JSON,TOML描述又太笨重,要的就是简简单单编码与解析。因此可以利用Scanner来完成。

import (
    "fmt" 
    "bufio"
    "bytes"
    "strings"
)

func main() {
    var str = "姓名;年龄;籍贯;性别\r\nTom,15,China,male"
    rd := strings.NewReader(str)

    //NewScanner接受实现io.Reader接口的参数,
    //因此解析的源可以是file,string,os.Stdin等等
    line := bufio.NewScanner(rd)
    //设定分隔方式,由于是函数作为参数,因此可以实现复杂的分隔方式,比如完整版csv格式分隔
    //分拆函数原型为
    //type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
    //语言自带换行符分隔
    line.Split(bufio.ScanLines)

    //循环拆分项
    for line.Scan() {
        //fmt.Println(line.Text())
        //每Scan一次可以通过line.Text()或者line.Bytes()获取分隔的单项
        item := bufio.NewScanner(strings.NewReader(line.Text()))
        item.Split(ScanItems)
        item.Scan()
        it1 := item.Text()
        item.Scan()
        it2 := item.Text()
        item.Scan()
        it3 := item.Text()
        item.Scan()
        it4 := item.Text()

        fmt.Println(it1 + " " + it2 + " " + it3 + " " + it4)

        if item.Err() != nil {
            //TODO: 解析过程中出现错误,但不一定会抛出异常
            fmt.Println(item.Err())
        }
    }
}

//逗号或分号 的自定义分隔
func ScanItems(data []byte, atEOF bool) (advance int, token []byte, err error) {
    if atEOF && len(data) == 0 {
        return 0, nil, nil
    }
    if i := bytes.IndexAny(data, ",;"); i >= 0 {
        return i + 1, data[0:i], nil
    }

    if atEOF {
        return len(data), data, nil
    }

    return 0, nil, nil
}

Output:
姓名 年龄 籍贯 性别
Tom 15 China male

你可能感兴趣的:(golang记录)