【问题标题】:weird output when parsing csv file解析csv文件时输出奇怪
【发布时间】:2018-02-28 13:33:03
【问题描述】:

我正在使用 golang 解析来自 google api 的 csv 文件,该文件以 utf-16 编码,下面的代码尝试读取一条记录(跳过标头)并打印该记录,但它给了我这样的输出很奇怪:

, v=/09/20 00:35:42 k=Smartfren Andromax AD681H

我猜这可能与utf-16编码有关,但不知道细节,这里是代码: 主包

import (
    "encoding/csv"
    "io"
    "log"
    "net/http"
    "strings"
)

var url = "http://storage.googleapis.com/play_public/supported_devices.csv"

func main() {

    resp, err := http.Get(url)
    if err != nil {
        return
    }
    defer resp.Body.Close()

    r := csv.NewReader(resp.Body)
    r.LazyQuotes = true
    r.FieldsPerRecord = -1
    // skip header
    r.Read()

    m := make(map[string]string)
    for {
        record, err := r.Read()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Println(err)
            continue
        }
        if len(record) >= 4 {
            m[strings.TrimSpace(record[3])] = strings.TrimSpace(record[1])
            for k, v := range m {
                log.Printf("k=%s, v=%s\n", k, v)
            }
            break
        }
    }
}

【问题讨论】:

    标签: csv go encoding utf-16


    【解决方案1】:

    正如您所怀疑的,输入数据必须从 UTF-16 编码字符流转换为 UTF-8 编码字符流。您可以使用 Go 子存储库包golang.org/x/text/encoding/unicode 来做到这一点:

    package main
    
    import (
        "encoding/csv"
        "io"
        "log"
        "net/http"
        "strings"
    
        "golang.org/x/text/encoding/unicode"
    )
    
    var url = "http://storage.googleapis.com/play_public/supported_devices.csv"
    
    func main() {
    
        resp, err := http.Get(url)
        if err != nil {
            return
        }
        defer resp.Body.Close()
    
        dec := unicode.UTF16(unicode.LittleEndian, unicode.UseBOM).NewDecoder()
        reader := dec.Reader(resp.Body)
    
        r := csv.NewReader(reader)
        r.LazyQuotes = true
        r.FieldsPerRecord = -1
        // skip header
        r.Read()
    
        m := make(map[string]string)
        for {
            record, err := r.Read()
            if err == io.EOF {
                break
            }
            if err != nil {
                log.Println(err)
                continue
            }
            if len(record) >= 4 {
                m[strings.TrimSpace(record[3])] = strings.TrimSpace(record[1])
                for k, v := range m {
                    log.Printf("k=%s, v=%s\n", k, v)
                }
                break
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-10-04
      • 1970-01-01
      • 2021-07-15
      • 1970-01-01
      • 2020-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多