读取之前清洁CSV文件。

huangapple go评论131阅读模式
英文:

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. 1|2
  2. "a|b

因此,我需要删除所有的双引号",我目前是在终端上使用sed 's/"//g'对整个文件进行操作,但我希望在Go脚本中进行删除。

在我读取文件的情况下,应该如何做到这一点:

  1. func processCSV(filepath string){
  2. file, err := os.Open("foo.csv")
  3. if err != nil {
  4. log.Fatal(err)
  5. }
  6. parser := csv.NewReader(file)
  7. parser.Comma = '|'
  8. // parser.LazyQuotes = true
  9. _, err = parser.Read() // 跳过标题
  10. for {
  11. record, err := parser.Read()
  12. if err == io.EOF {
  13. break
  14. }
  15. if err != nil {
  16. log.Fatal(err)
  17. }
  18. // 处理记录
  19. }
  20. }
英文:

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. 1|2
  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:

  1. func processCSV(filepath string){
  2. file, err := os.Open("foo.csv")
  3. if err != nil {
  4. log.Fatal(err)
  5. }
  6. parser := csv.NewReader(file)
  7. parser.Comma = '|'
  8. // parser.LazyQuotes = true
  9. _, err = parser.Read() // skip headers
  10. for {
  11. record, err := parser.Read()
  12. if err == io.EOF {
  13. break
  14. }
  15. if err != nil {
  16. log.Fatal(err)
  17. }
  18. // process record
  19. }
  20. }

答案1

得分: 3

创建一个io.Reader,通过底层的io.Reader读取的数据中去除引号。

  1. // rmquote 从r中读取数据时去除引号。
  2. type rmquote struct {
  3. r io.Reader
  4. }
  5. func (c rmquote) Read(p []byte) (int, error) {
  6. n, err := c.r.Read(p)
  7. // i是下面循环的输出位置
  8. i := 0
  9. // 对于从文件中读取的每个字节
  10. for _, b := range p[:n] {
  11. // 跳过引号
  12. if b == '"' {
  13. continue
  14. }
  15. // 将字节复制到输出位置并移动位置
  16. p[i] = b
  17. i++
  18. }
  19. // 输出位置就是新的长度
  20. return i, err
  21. }
  22. // 在CSV读取器和文件之间使用它:
  23. parser := csv.NewReader(rmquote{file})
英文:

Create an io.Reader that removes quotes from data read through an underlying io.Reader.

  1. // rmquote reads r with " removed.
  2. type rmquote struct {
  3. r io.Reader
  4. }
  5. func (c rmquote) Read(p []byte) (int, error) {
  6. n, err := c.r.Read(p)
  7. // i is output position for loop below
  8. i := 0
  9. // for each byte read from the file
  10. for _, b := range p[:n] {
  11. // skip quotes
  12. if b == '"' {
  13. continue
  14. }
  15. // copy byte to output position and advance position
  16. p[i] = b
  17. i++
  18. }
  19. // output position is the new length
  20. return i, err
  21. }

Plumb it in between the CSV reader and file:

  1. parser := csv.NewReader(rmquote{file})

huangapple
  • 本文由 发表于 2022年6月9日 23:41:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/72563139.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定