4

解决 CSV 文件的第一列不能解析

 8 months ago
source link: https://www.lfhacks.com/tech/unable-to-unmarshal-first-column-of-csv/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

解决 CSV 文件的第一列不能解析

3657.jpg
扫一扫,转发文章

用 Python 或者 go 语言解析 CSV 文件的时候,有时候会遇到不能解析出第一列的情况,尤其是当这个CSV文件来自 Excel的时候,容易出现这种现象。本文试着解决这个问题。

其实在 向 Elastic Search 中批量导入 Excel 这篇文章中已经遇到了这个问题。

看这样一个使用 Excel 软件创建的 csv 文件:

csv.png

( ☝Excel 创建的 csv )

用文本编辑器打开 csv 文件,正如文本看到的是用逗号分隔的文本:

csv2.png

( ☝Excel 创建的 csv )

我们希望用 Python 或者 Go 语言解析这个 csv, 使用的代码如下:

使用 Python 解析

运行下面的代码用来查看每一行的内容:

import csv with open("some.csv", 'r') as f: reader = csv.DictReader(f) for row in reader: print(row["Id"], row["Name"], row["Age"])

运行这段代码,会报错:找不到 Id 这个字段:

Traceback (most recent call last): File "some.py", line 6, in <module> print(row["Id"], row["Name"], row["Age"])KeyError: 'Id'

使用 Go 解析

运行下面的代码用来寻找名字叫 Id 的文本值:

package main import ( "encoding/csv" "fmt" "io" "log" "os") func main() { f, err := os.Open("some.csv") if err != nil { log.Fatalf("Error: %s", err) } defer f.Close() r := csv.NewReader(f) for { record, err := r.Read() if err == io.EOF { break } if err != nil { log.Fatalf("Read csv error: %s", err) } for _, field := range record { if field == "Id" { fmt.Println(field) } } }}

得到结果为空,什么也不打印。

用 16进制编辑器查看文件,会发现文件头有三个字节的 BOM 字符:

csv3.png

如果解析 csv 的库不去主动处理这三个字符,就会被当作第一个字段名的一部分。

Python 的解决方法

在打开文件的 open 函数中,指定解码方式为 encoding='utf_8_sig'

import csv with open("some.csv", 'r', encoding='utf_8_sig') as f: reader = csv.DictReader(f) for row in reader: print(row["Id"], row["Name"], row["Age"])

顺利读出 csv 文件的结构:

1 Alice 122 Bob 83 Charlie 10

Go 语言的解决方法

使用第三方库 utfbom,可以方便的去掉 BOM 字符:

go get -u github.com/dimchansky/utfbom

原生 csv 库

package main import ( "encoding/csv" "fmt" "io" "log" "os" "github.com/dimchansky/utfbom") func main() { f, err := os.Open("some.csv") if err != nil { log.Fatalf("Error: %s", err) } defer f.Close() r := csv.NewReader(utfbom.SkipOnly(f)) for { record, err := r.Read() if err == io.EOF { break } if err != nil { log.Fatalf("Read csv error: %s", err) } for _, field := range record { if field == "Id" { fmt.Println(field) } } }}

如果您对本站内容有疑问或者寻求合作,欢迎 联系邮箱 。邮箱已到剪贴板


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK