Go中的CSV解析器由于尾随空格而中断

时间:2018-09-19 12:26:16

标签: csv go

我们正在尝试使用Go的encoding / csv包解析一个csv文件。这个特定的csv有点特殊,每行都有一个尾随空格。当尝试使用带引号的字段对此csv进行解码时,该包会中断,因为它需要换行符,分隔符或引号。尾随空格是不希望的。

您将如何处理此案?您知道我们可以使用的另一个解析器吗?

编辑:

f,err := os.Open("file.go")
// err etc..
csvr := csv.NewReader(f)
csvr.Comma = csvDelimiter
for {
   rowAsSlice, err := csvr.Read()
   // Handle row and errors etc.
}

编辑2: CSV示例,请注意尾随空格!

"RECORD_TYPE","COMPANY_SHORTNAME" 
"HDR","COMPANY_EXAMPLE" 

1 个答案:

答案 0 :(得分:3)

一种可能的解决方案是将源文件阅读器包装到一个自定义阅读器中,该自定义阅读器的Read(...)方法会悄悄地从基础阅读器实际读取的内容中删除尾随空白。 csv.Reader可以直接使用该类型。

例如(here):

type TrimReader struct{ io.Reader }

var trailingws = regexp.MustCompile(` +\r?\n`)

func (tr TrimReader) Read(bs []byte) (int, error) {
  // Perform the requested read on the given reader.
  n, err := tr.Reader.Read(bs)
  if err != nil {
    return n, err
  }

  // Remove trailing whitespace from each line.
  lines := string(bs[:n])
  trimmed := []byte(trailingws.ReplaceAllString(lines, "\n"))
  copy(bs, trimmed)
  return len(trimmed), nil
}

func main() {
  file, err := file.Open("myfile.csv")
  // TODO: handle err...

  csvr := csv.NewReader(TrimReader{file})

  for {
    record, err := csvr.Read()
    if err == io.EOF {
      break
    }
    fmt.Printf("LINE: record=%#v, err=%v\n", record, err)
  }
  // LINE: record=[]string{"RECORD_TYPE", "COMPANY_SHORTNAME"}, err=<nil>
  // LINE: record=[]string{"HDR", "COMPANY_EXAMPLE"}, err=<nil>
}

请注意,正如评论者@svsd指出的那样,此处存在一个细微的错误,如果直到后续调用之前都未读取行终止符,则尾随空格仍然可以通过。您可以通过缓冲或最好只是对这些CSV文件进行预处理,以在尝试解析它们之前删除尾随空白的方法来解决。