用 Python 或者 go 语言解析 CSV 文件的时候,有时候会遇到不能解析出第一列的情况,尤其是当这个CSV文件来自 Excel的时候,容易出现这种现象。本文试着解决这个问题。
问题描述
其实在 向 Elastic Search 中批量导入 Excel 这篇文章中已经遇到了这个问题。
看这样一个使用 Excel 软件创建的 csv 文件:
( ☝Excel 创建的 csv )
用文本编辑器打开 csv 文件,正如文本看到的是用逗号分隔的文本:
( ☝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 字符:
如果解析 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 12
2 Bob 8
3 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)
}
}
}
}
如果您对本文有疑问或者寻求合作,欢迎 联系邮箱 。邮箱已到剪贴板
给个免费的赞吧~
精彩评论
本站 是个人网站,采用 署名协议 CC-BY-NC 授权。
欢迎转载,请保留原文链接 https://www.lfhacks.com/tech/unable-to-unmarshal-first-column-of-csv/ ,且不得用于商业用途。