始终引用 CSV 值

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

Always quote csv values

问题

我想引用CSV文档中的所有字段。有没有一种方法可以修改golang的csv模块而不必复制所有代码?在另一种语言中,我可以简单地从csv.Writer继承并覆盖fieldNeedsQuotes,但在Go中这是不可能的,对吗?

英文:

I want to quote all fields in a CSV document. Is there a way to modify golang's csv module without having to copy all the code? In another language, I'd simply inherit from csv.Writer and override fieldNeedsQuotes, but that is not possible in Go, or is it?

答案1

得分: 1

我明白了,这是一个旧问题。但最近我遇到了同样的问题,并创建了一个名为altcsv的小型库,通过扩展Golang的encoding/csv来解决。

如果其他人也对此感兴趣,可以使用以下库:
https://github.com/tushar2708/altcsv

它与现有的CSV库向后兼容。我计划在将来为该库添加更多类似Python的CSV接口。

从CSV文件中读取:

fileRdr, _ = os.Open("/tmp/custom_csv_file.txt")
csvRdr := altcsv.NewReader(fileRdr)
content := csvReader.ReadAll()

写入CSV文件:

headers := []string{"hero_name", "alter_ego", "identity"}
fileWtr, _ := os.Create("/tmp/all_quotes_csv_file.txt")
csvWtr := altcsv.NewWriter(csvH)
csvWtr.AllQuotes = true   // 将每个字段用双引号括起来
csvWtr.Write(headers)
csvWtr.Write([]string{"Spider-Man", "Peter Parker", "Secret Identity"})
csvWtr.Write([]string{"Captain America", "Steven Rogers", "Public Identity"})
csvWtr.Write([]string{"Thor", "Thor Odinson", "No dual Identity"})
csvWtr.Flush()
fileWtr.Close()
英文:

I see, it's an old question. But I recently faced the same problem, and created a small library altcsv, by extending the Golang's encoding/csv.

If someone else is wondering about the same, you can use the below library:
https://github.com/tushar2708/altcsv

It's backward compatible with existing CSV library. I plan to add more python-like CSV interface to the same in future.

Reading from a CSV file:

fileRdr, _ = os.Open("/tmp/custom_csv_file.txt")
csvRdr := altcsv.NewReader(fileRdr)
content := csvReader.ReadAll()

Writing to a CSV file:

headers = []string{"hero_name", "alter_ego", "identity"}
fileWtr, _ := os.Create("/tmp/all_quotes_csv_file.txt")
csvWtr := altcsv.NewWriter(csvH)
csvWtr.AllQuotes = true   // surround each field with '"'
csvWtr.Write(headers)
csvWtr.Write([]string{"Spider-Man", "Peter Parker", "Secret Identity"})
csvWtr.Write([]string{"Captain America", "Steven Rogers", "Public Identity"})
csvWtr.Write([]string{"Thor", "Thor Odinson", "No dual Identity"})
csvWtr.Flush()
fileWtr.Close()

答案2

得分: 0

Matt和Volker已经说过,你可以复制这个模块并进行修改。

你也可以使用一个Writer包装器,但我认为这会更加复杂。
以下是我作为概念验证的尝试(不要使用*):

type quoteWriter struct {
    w io.Writer
}

func (w quoteWriter) Write(p []byte) (n int, err error) {
    q := make([]byte, 0)
    quoted := true
    quoted = (p[0] == '"')
    if !quoted {
        //开始字段引用
        q = append(q, '"')
    }

    for i, v := range p {
        //我们检查新字段或行的“引用”状态
        //这是一个简化
        if v == ',' || v == '\n' {
            if !quoted { //结束字段引用
                q = append(q, '"')
            }
            //复制当前字节
            q = append(q, v)

            //下一个字节是否为引号?
            if len(p) > i+1 {
                quoted = (p[i+1] == '"')
            }
            if !quoted { //开始字段引用
                q = append(q, '"')
            }
        } else {
            q = append(q, v)
        }
    }

    return w.w.Write(q)
}

下面是应用了概念验证的示例,来自csv#Writer测试(http://golang.org/src/pkg/encoding/csv/writer_test.go):

http://play.golang.org/p/wovYUkt6Vq

不要使用* 请注意,我没有检查所有情况,例如,逗号是否在引号内或不在引号内,所以你需要检查并进行适应。
我还建议复制并修改csv包。

英文:

Matt and Volker already said that you can copy the module and modify it.

You can use a Writer wrapper as well, but I think it's a bit more complex.
See my attempt as a proof of concept (not to be used*).

type quoteWriter struct {
	w io.Writer
}

func (w quoteWriter) Write(p []byte) (n int, err error) {
	q := make([]byte, 0)
	quoted := true
	quoted = (p[0] == '"')
	if !quoted {
		//begin field quote
		q = append(q, '"')
	}

	for i, v := range p {
		//We check the "quotation" status for new field or line
		//This is a simplification
		if v == ',' || v == '\n' {
			if !quoted { //end field quote
				q = append(q, '"')
			}
			//copy current byte
			q = append(q, v)

			//is next byte quote?
			if len(p) > i+1 {
				quoted = (p[i+1] == '"')
			}
			if !quoted { //begin field quote
				q = append(q, '"')
			}
		} else {
			q = append(q, v)
		}
	}

	return w.w.Write(q)
}

See below the example coming from the csv#Writer test (http://golang.org/src/pkg/encoding/csv/writer_test.go) with the proof of concept applied:

http://play.golang.org/p/wovYUkt6Vq

not to be used* Please, notice that I haven't checked all cases, for instance, if a comma is within a quoted text or not, so you would need to check and adapt it.
I also recommend to copy and modify the csv package.

huangapple
  • 本文由 发表于 2014年1月24日 11:57:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/21324133.html
匿名

发表评论

匿名网友

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

确定