Source File
writer.go
Belonging Package
encoding/csv
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package csv
import (
)
// A Writer writes records using CSV encoding.
//
// As returned by [NewWriter], a Writer writes records terminated by a
// newline and uses ',' as the field delimiter. The exported fields can be
// changed to customize the details before
// the first call to [Writer.Write] or [Writer.WriteAll].
//
// [Writer.Comma] is the field delimiter.
//
// If [Writer.UseCRLF] is true,
// the Writer ends each output line with \r\n instead of \n.
//
// The writes of individual records are buffered.
// After all data has been written, the client should call the
// [Writer.Flush] method to guarantee all data has been forwarded to
// the underlying [io.Writer]. Any errors that occurred should
// be checked by calling the [Writer.Error] method.
type Writer struct {
Comma rune // Field delimiter (set to ',' by NewWriter)
UseCRLF bool // True to use \r\n as the line terminator
w *bufio.Writer
}
// NewWriter returns a new Writer that writes to w.
func ( io.Writer) *Writer {
return &Writer{
Comma: ',',
w: bufio.NewWriter(),
}
}
// Write writes a single CSV record to w along with any necessary quoting.
// A record is a slice of strings with each string being one field.
// Writes are buffered, so [Writer.Flush] must eventually be called to ensure
// that the record is written to the underlying [io.Writer].
func ( *Writer) ( []string) error {
if !validDelim(.Comma) {
return errInvalidDelim
}
for , := range {
if > 0 {
if , := .w.WriteRune(.Comma); != nil {
return
}
}
// If we don't have to have a quoted field then just
// write out the field and continue to the next field.
if !.fieldNeedsQuotes() {
if , := .w.WriteString(); != nil {
return
}
continue
}
if := .w.WriteByte('"'); != nil {
return
}
for len() > 0 {
// Search for special characters.
:= strings.IndexAny(, "\"\r\n")
if < 0 {
= len()
}
// Copy verbatim everything before the special character.
if , := .w.WriteString([:]); != nil {
return
}
= [:]
// Encode the special character.
if len() > 0 {
var error
switch [0] {
case '"':
_, = .w.WriteString(`""`)
case '\r':
if !.UseCRLF {
= .w.WriteByte('\r')
}
case '\n':
if .UseCRLF {
_, = .w.WriteString("\r\n")
} else {
= .w.WriteByte('\n')
}
}
= [1:]
if != nil {
return
}
}
}
if := .w.WriteByte('"'); != nil {
return
}
}
var error
if .UseCRLF {
_, = .w.WriteString("\r\n")
} else {
= .w.WriteByte('\n')
}
return
}
// Flush writes any buffered data to the underlying [io.Writer].
// To check if an error occurred during Flush, call [Writer.Error].
func ( *Writer) () {
.w.Flush()
}
// Error reports any error that has occurred during
// a previous [Writer.Write] or [Writer.Flush].
func ( *Writer) () error {
, := .w.Write(nil)
return
}
// WriteAll writes multiple CSV records to w using [Writer.Write] and
// then calls [Writer.Flush], returning any error from the Flush.
func ( *Writer) ( [][]string) error {
for , := range {
:= .Write()
if != nil {
return
}
}
return .w.Flush()
}
// fieldNeedsQuotes reports whether our field must be enclosed in quotes.
// Fields with a Comma, fields with a quote or newline, and
// fields which start with a space must be enclosed in quotes.
// We used to quote empty strings, but we do not anymore (as of Go 1.4).
// The two representations should be equivalent, but Postgres distinguishes
// quoted vs non-quoted empty string during database imports, and it has
// an option to force the quoted behavior for non-quoted CSV but it has
// no option to force the non-quoted behavior for quoted CSV, making
// CSV with quoted empty strings strictly less useful.
// Not quoting the empty string also makes this package match the behavior
// of Microsoft Excel and Google Drive.
// For Postgres, quote the data terminating string `\.`.
func ( *Writer) ( string) bool {
if == "" {
return false
}
if == `\.` {
return true
}
if .Comma < utf8.RuneSelf {
for := 0; < len(); ++ {
:= []
if == '\n' || == '\r' || == '"' || == byte(.Comma) {
return true
}
}
} else {
if strings.ContainsRune(, .Comma) || strings.ContainsAny(, "\"\r\n") {
return true
}
}
, := utf8.DecodeRuneInString()
return unicode.IsSpace()
}
The pages are generated with Golds v0.7.0-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |