在Go的encoding/csv中,引号括起来的字符串的CSV结果很奇怪。

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

Strange CSV result for quoted strings in go encoding/csv

问题

我有一小段代码让我整个周末都忙碌。

package main

import (
	"encoding/csv"
	"fmt"
	"log"
	"os"
)

func main() {
	f, err := os.Create("./test.csv")
	if err != nil {
		log.Fatal("Error: %s", err)
	}
	defer f.Close()

	w := csv.NewWriter(f)
	var record []string
	record = append(record, "Unquoted string")
	s := "Cr@zy text with , and \\ and \" etc"
	record = append(record, s)
	fmt.Println(record)
	w.Write(record)

	record = make([]string, 0)
	record = append(record, "Quoted string")
	s = fmt.Sprintf("%q", s)
	record = append(record, s)
	fmt.Println(record)
	w.Write(record)

	w.Flush()
}

运行后输出:

[Unquoted string Cr@zy text with , and \ and " etc]
[Quoted string "Cr@zy text with , and \\ and \" etc"]

第二个带引号的文本正是我希望在CSV中看到的,但实际上我得到了这个:

Unquoted string,"Cr@zy text with , and \ and "" etc"
Quoted string,"""Cr@zy text with , and \\ and \" etc"""

这些额外的引号是从哪里来的,我该如何避免它们?
我尝试了很多方法,包括使用strings.Quote等,但似乎找不到完美的解决方案。请帮忙!

英文:

I have this little bit of code that kept me busy the whole weekend.

package main

import (
	"encoding/csv"
	"fmt"
	"log"
	"os"
)

func main() {
	f, err := os.Create("./test.csv")
	if err != nil {
		log.Fatal("Error: %s", err)
	}
	defer f.Close()

	w := csv.NewWriter(f)
	var record []string
	record = append(record, "Unquoted string")
	s := "Cr@zy text with , and \\ and \" etc"
	record = append(record, s)
	fmt.Println(record)
	w.Write(record)

	record = make([]string, 0)
	record = append(record, "Quoted string")
	s = fmt.Sprintf("%q", s)
	record = append(record, s)
	fmt.Println(record)
	w.Write(record)

	w.Flush()
}

When run it prints out:

[Unquoted string Cr@zy text with , and \ and " etc]
[Quoted string "Cr@zy text with , and \\ and \" etc"]

The second, quoted text is exactly what I would wish to see in the CSV, but instead I get this:

Unquoted string,"Cr@zy text with , and \ and "" etc"
Quoted string,"""Cr@zy text with , and \\ and \"" etc"""

Where do those extra quotes come from and how do I avoid them?
I have tried a number of things, including using strings.Quote and some such but I can't seem to find a perfect solution. Help, please?

答案1

得分: 6

这是存储数据为CSV格式的标准的一部分。
为了解析的原因,需要对双引号字符进行转义。

在字段中,一个(双重)引号字符必须由两个(双重)引号字符表示。
来源:http://en.wikipedia.org/wiki/Comma-separated_values

你不需要担心,因为CSV读取器会取消转义双引号。

示例:

package main

import (
    "encoding/csv"
    "fmt"
    "os"
)
func checkError(e error){
    if e != nil {
        panic(e)
    }
}
func writeCSV(){
    fmt.Println("Writing csv")
    f, err := os.Create("./test.csv")
    checkError(err)
    defer f.Close()

    w := csv.NewWriter(f)
    s := "Cr@zy text with , and \\ and \" etc"
    record := []string{ 
      "Unquoted string",
      s,
    }
    fmt.Println(record)
    w.Write(record)

    record = []string{ 
      "Quoted string",
      fmt.Sprintf("%q",s),
    }
    fmt.Println(record)
    w.Write(record)
    w.Flush()
}
func readCSV(){
    fmt.Println("Reading csv")
    file, err := os.Open("./test.csv")
    defer file.Close();
    cr := csv.NewReader(file)
    records, err := cr.ReadAll()
    checkError(err)
    for _, record := range records {
        fmt.Println(record)
    }
}
func main() {
   writeCSV()
   readCSV()
}

输出

Writing csv
[Unquoted string Cr@zy text with , and \ and " etc]
[Quoted string "Cr@zy text with , and \\ and \" etc"]
Reading csv
[Unquoted string Cr@zy text with , and \ and " etc]
[Quoted string "Cr@zy text with , and \\ and \" etc"]

这是write函数的代码。
func (w *Writer) Write(record []string) (err error)

英文:

It's part of the standard for storing data as CSV.
Double quote characters need to be escaped for parsing reasons.

<blockquote>A (double) quote character in a field must be represented by two (double) quote characters.</blockquote>
From: http://en.wikipedia.org/wiki/Comma-separated_values

You don't really have to worry because the CSV reader un-escapes the double quote.

Example:

package main

import (
    &quot;encoding/csv&quot;
    &quot;fmt&quot;
    &quot;os&quot;
)
func checkError(e error){
    if e != nil {
	    panic(e)
    }
}
func writeCSV(){
    fmt.Println(&quot;Writing csv&quot;)
    f, err := os.Create(&quot;./test.csv&quot;)
    checkError(err)
    defer f.Close()

    w := csv.NewWriter(f)
    s := &quot;Cr@zy text with , and \\ and \&quot; etc&quot;
    record := []string{ 
      &quot;Unquoted string&quot;,
      s,
    }
    fmt.Println(record)
    w.Write(record)

    record = []string{ 
      &quot;Quoted string&quot;,
      fmt.Sprintf(&quot;%q&quot;,s),
    }
    fmt.Println(record)
    w.Write(record)
    w.Flush()
}
func readCSV(){
    fmt.Println(&quot;Reading csv&quot;)
    file, err := os.Open(&quot;./test.csv&quot;)
    defer file.Close();
    cr := csv.NewReader(file)
    records, err := cr.ReadAll()
    checkError(err)
    for _, record := range records {
        fmt.Println(record)
    }
}
func main() {
   writeCSV()
   readCSV()
}

Output

Writing csv
[Unquoted string Cr@zy text with , and \ and &quot; etc]
[Quoted string &quot;Cr@zy text with , and \\ and \&quot; etc&quot;]
Reading csv
[Unquoted string Cr@zy text with , and \ and &quot; etc]
[Quoted string &quot;Cr@zy text with , and \\ and \&quot; etc&quot;]

Here's the code for the write function.
func (w *Writer) Write(record []string) (err error)

答案2

得分: 4

我有一个包含双引号字符串的CSV文件,类似于:

> text;//*[@class="price"]/span;text

但是CSV读取器在读取CSV文件时出现错误。
以下是一些有用的信息:

reader := csv.NewReader(file)
reader.LazyQuotes = true
英文:

I have csv file with line with double quote string like:

> text;//*[@class="price"]/span;text

And csv Reader generate error to read csv file.
Helpful was:

reader := csv.NewReader(file)
reader.LazyQuotes = true

答案3

得分: -1

s变量的值不是你想的那样。http://play.golang.org/p/vAEYkINWnm

英文:

The s variable's value is not what you think it is. http://play.golang.org/p/vAEYkINWnm

huangapple
  • 本文由 发表于 2013年12月9日 05:02:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/20459038.html
匿名

发表评论

匿名网友

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

确定