英文:
Cleaning CSV file before reading
问题
我正在使用encoding/csv
库读取一个大型的CSV文件。
但是这个文件有点非标准,包含了非转义的引号"
,导致在parser.Read()
处出现错误:
>2022/06/09 17:33:54 第2行第5列解析错误:引号在引用字段中多余或缺失
如果我使用parser.LazyQuotes = true
,则会得到:
>2022/06/09 17:34:15 第2行记录:字段数量错误
有问题的CSV文件(已简化为最小)foo.csv
:
1|2
"a|b
因此,我需要删除所有的双引号"
,我目前是在终端上使用sed 's/"//g'
对整个文件进行操作,但我希望在Go脚本中进行删除。
在我读取文件的情况下,应该如何做到这一点:
func processCSV(filepath string){
file, err := os.Open("foo.csv")
if err != nil {
log.Fatal(err)
}
parser := csv.NewReader(file)
parser.Comma = '|'
// parser.LazyQuotes = true
_, err = parser.Read() // 跳过标题
for {
record, err := parser.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
// 处理记录
}
}
英文:
I'm reading a big CSV file with encoding/csv
library.
But this file is a bit non-standard and contains non-escaped quotes "
breaking the reader at parser.Read()
:
>2022/06/09 17:33:54 parse error on line 2, column 5: extraneous or missing " in quoted-field
And if I use parser.LazyQuotes = true
, I'm getting:
> 2022/06/09 17:34:15 record on line 2: wrong number of fields
Faulty CSV file (reduced to its minimum) foo.csv
:
1|2
"a|b
So I need to remove all occurences of double quotes "
and I'm currently doing it on the whole file from terminal using sed 's/"//g'
, but I want to remove it from Go script instead.
How should I do it knowing that I'm reading the file like this:
func processCSV(filepath string){
file, err := os.Open("foo.csv")
if err != nil {
log.Fatal(err)
}
parser := csv.NewReader(file)
parser.Comma = '|'
// parser.LazyQuotes = true
_, err = parser.Read() // skip headers
for {
record, err := parser.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
// process record
}
}
答案1
得分: 3
创建一个io.Reader,通过底层的io.Reader读取的数据中去除引号。
// rmquote 从r中读取数据时去除引号。
type rmquote struct {
r io.Reader
}
func (c rmquote) Read(p []byte) (int, error) {
n, err := c.r.Read(p)
// i是下面循环的输出位置
i := 0
// 对于从文件中读取的每个字节
for _, b := range p[:n] {
// 跳过引号
if b == '"' {
continue
}
// 将字节复制到输出位置并移动位置
p[i] = b
i++
}
// 输出位置就是新的长度
return i, err
}
// 在CSV读取器和文件之间使用它:
parser := csv.NewReader(rmquote{file})
英文:
Create an io.Reader that removes quotes from data read through an underlying io.Reader.
// rmquote reads r with " removed.
type rmquote struct {
r io.Reader
}
func (c rmquote) Read(p []byte) (int, error) {
n, err := c.r.Read(p)
// i is output position for loop below
i := 0
// for each byte read from the file
for _, b := range p[:n] {
// skip quotes
if b == '"' {
continue
}
// copy byte to output position and advance position
p[i] = b
i++
}
// output position is the new length
return i, err
}
Plumb it in between the CSV reader and file:
parser := csv.NewReader(rmquote{file})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论