Documentation ¶
Overview ¶
Package easycsv provides API to read CSV files with less boilerplate code in Go.
Overview guideline: https://github.com/yunabe/easycsv/blob/master/README.md
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var Break = errors.New("break")
Break is the error returned by the callback passed to Loop to terminate the loop.
Functions ¶
This section is empty.
Types ¶
type Option ¶
type Option struct { // Comma is the field delimiter. // For exampoe, if '\t' is set to Comma, Reader reads files as TSV files. Comma rune // Comment, if not 0, is the comment character. Lines beginning with the character without preceding whitespace are ignored. Comment rune // Allow lazy parsing of quotes, default to false LazyQuotes bool // If negative, Reader does not check the number of fields per record // If 0, this option does not update Reader // If positive, Reader requires all records to have this number of fields FieldsPerRecord int // Decoders is the map to define custom encodings. Decoders map[string]interface{} // Custom decoders to parse specific types. TypeDecoders map[reflect.Type]interface{} // TODO: Support AutoIndex AutoIndex bool // TODO: Support AutoName AutoName bool }
Option specifies the spec of Reader.
Example (Decoders) ¶
r := NewReader(bytes.NewBufferString("name,birthday\nAlice,1980-12-30\nBob,1975-06-09"), Option{ Decoders: map[string]interface{}{ "date": func(s string) (time.Time, error) { return time.Parse("2006-01-02", s) }, }, }) var entry struct { Name string `name:"name"` Birth time.Time `name:"birthday" enc:"date"` } for r.Read(&entry) { fmt.Print(entry) } if err := r.Done(); err != nil { log.Fatalf("Failed: %v\n", err) }
Output: {Alice 1980-12-30 00:00:00 +0000 UTC}{Bob 1975-06-09 00:00:00 +0000 UTC}
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader provides a convenient interface for reading csv.
Example (Encodings) ¶
r := NewReader(bytes.NewReader([]byte("010,010,010"))) var entry struct { Deci int `index:"0" enc:"deci"` Oct int `index:"1" enc:"oct"` Hex int `index:"2" enc:"hex"` } for r.Read(&entry) { fmt.Print(entry) } if err := r.Done(); err != nil { log.Fatalf("Failed to read: %v", err) }
Output: {10 8 16}
Example (Loop) ¶
r := NewReaderFile("testdata/sample.csv") err := r.Loop(func(entry *struct { Name string `index:"0"` Age int `index:"1"` }) error { fmt.Print(entry) return nil }) if err != nil { log.Fatalf("Failed to read a CSV file: %v", err) }
Output: &{Alice 10}&{Bob 20}
Example (Read) ¶
r := NewReaderFile("testdata/sample.csv") var entry struct { Name string `index:"0"` Age int `index:"1"` } for r.Read(&entry) { fmt.Print(entry) } if err := r.Done(); err != nil { log.Fatalf("Failed to read a CSV file: %v", err) }
Output: {Alice 10}{Bob 20}
Example (ReadAll) ¶
r := NewReaderFile("testdata/sample.csv") var entry []struct { Name string `index:"0"` Age int `index:"1"` } if err := r.ReadAll(&entry); err != nil { log.Fatalf("Failed to read a CSV file: %v", err) } fmt.Println(entry)
Output: [{Alice 10} {Bob 20}]
Example (TSV) ¶
r := NewReaderFile("testdata/sample.tsv", Option{ Comma: '\t', }) var entry struct { Name string `index:"0"` Age int `index:"1"` } for r.Read(&entry) { fmt.Print(entry) } if err := r.Done(); err != nil { log.Fatalf("Failed to read a CSV file: %v", err) }
Output: {Alice 10}{Bob 20}
Example (TypeEncodings) ¶
r := NewReader(bytes.NewReader([]byte("2017-01-02,2016-02-03\n2015-03-04,2014-04-05")), Option{TypeDecoders: map[reflect.Type]interface{}{ reflect.TypeOf(time.Time{}): func(s string) (time.Time, error) { return time.Parse("2006-01-02", s) }, }}) var entry []time.Time for r.Read(&entry) { for _, e := range entry { fmt.Print(e.Format("2006/1/2"), ";") } } if err := r.Done(); err != nil { log.Fatalf("Failed to read: %v", err) }
Output: 2017/1/2;2016/2/3;2015/3/4;2014/4/5;
func NewReadCloser ¶
func NewReadCloser(r io.ReadCloser, opts ...Option) *Reader
NewReadCloser returns a new Reader to read CSV from r. Reader instantiated with NewReadCloser closes r automatically when Done() is called.
func NewReaderFile ¶
NewReaderFile returns a new Reader to read CSV from the file path.
func (*Reader) Done ¶
Done returns the first non-EOF error that was encountered by the Reader. Done also closes the internal Closer if the Reader is instantiated with NewReaderCloser.
You need to use Done when you read CSV with Read method to check errors and close files behind. You don't use Done when you read CSV with ReadAll and Loop because they call Done internally.
func (*Reader) DoneDefer ¶
DoneDefer does the same thing as Done does. But it outputs an error to the argument. DoneDefer does not overwrite an error if an error is already stored in err. DoneDefer is useful to call Done from defer statement.
Example ¶
f := func() (err error) { r := NewReaderFile("testdata/sample.csv") defer r.DoneDefer(&err) var entry struct { Name string `index:"3"` } // This fails with a index-out-of-range error. for r.Read(&entry) { err = fmt.Errorf("This block must not be executed") } return } err := f() if err != nil { fmt.Printf("Failed: %v", err) }
Output: Failed: Accessed index 3 though the size of the row is 2
func (*Reader) LineNumber ¶
LineNumber returns the current position of r in the input (1-based line number). The behavior of LineNumber is undefined if it is called before Read operations or after r reached to EOF or an error.
Example (Reader) ¶
r := NewReaderFile("testdata/sample.csv") var entry struct { Name string `index:"0"` Age int `index:"1"` } bob := "Bob" lino := 0 for r.Read(&entry) { if entry.Name == bob { lino = r.LineNumber() } } if lino > 0 { fmt.Printf("Found %s at line %d", bob, lino) }
Output: Found Bob at line 2
func (*Reader) Loop ¶
Loop reads from r until an error or EOF and invokes body everytime it reads a line. body should be a function which has no return value or returns bool or error. If body returns false or an error, Loop stops reading r. If body does not have a return value, Loop does not stop until an error or EOF. If body returns error and you want to terminate Loop without reporting an error, returns easycsv.Break in body.
Also, body must receive one argument. The argument must be a pointer to a struct, a struct or a pointer to a slice. The line of csv is automatically converted to the struct or the slice based on the rule described above.
Loop returns an error if it encounters an error and exits the loop.
func (*Reader) Read ¶
Read reads one line from csv and store values in the line to e. The argument e must be a pointer to a struct or a pointer to a slice. Read returns false when it encounters an error or EOF.
func (*Reader) ReadAll ¶
ReadAll reads all rows from csv and store it into the slice s. s must be a pointer to a slice of a struct (e.g. *[]entry) or a pointer to a slice of primitive types (e.g. *[][]int). ReadAll reports an error if it encounters an error while reading the input. Also, ReadAll closes the file behind r automatically.