Reader and writer for comma-separated values (`CSV`) files, per [[ RFC 4180 ; https://tools.ietf.org/html/rfc4180.html ]]. Example: package main import "core:fmt" import "core:encoding/csv" import "core:os" // Requires keeping the entire CSV file in memory at once iterate_csv_from_string :: proc(filename: string) { r: csv.Reader r.trim_leading_space = true r.reuse_record = true // Without it you have to delete(record) r.reuse_record_buffer = true // Without it you have to each of the fields within it defer csv.reader_destroy(&r) csv_data, csv_err := os.read_entire_file(filename, context.allocator) defer delete(csv_data) if csv_err == nil { csv.reader_init_with_string(&r, string(csv_data)) } else { fmt.eprintfln("Unable to open file: %v. Error: %v", filename, csv_err) return } for r, i, err in csv.iterator_next(&r) { if err != nil { /* Do something with error */ } for f, j in r { fmt.printfln("Record %v, field %v: %q", i, j, f) } } } // Reads the CSV as it's processed (with a small buffer) iterate_csv_from_stream :: proc(filename: string) { fmt.printfln("Hellope from %v", filename) r: csv.Reader r.trim_leading_space = true r.reuse_record = true // Without it you have to delete(record) r.reuse_record_buffer = true // Without it you have to delete each of the fields within it defer csv.reader_destroy(&r) handle, err := os.open(filename) defer os.close(handle) if err != nil { fmt.eprintfln("Unable to open file: %v. Error: %v", filename, err) return } csv.reader_init(&r, handle.stream) for r, i in csv.iterator_next(&r) { for f, j in r { fmt.printfln("Record %v, field %v: %q", i, j, f) } } fmt.printfln("Error: %v", csv.iterator_last_error(r)) } // Read all records at once read_csv_from_string :: proc(filename: string) { r: csv.Reader r.trim_leading_space = true defer csv.reader_destroy(&r) csv_data, csv_err := os.read_entire_file(filename, context.allocator) defer delete(csv_data, context.allocator) if err != nil { fmt.eprintfln("Unable to open file: %v. Error: %v", filename, csv_err) return } csv.reader_init_with_string(&r, string(csv_data)) records, err := csv.read_all(&r) if err != nil { /* Do something with CSV parse error */ } defer { for record in records { for field in record { delete(field) } delete(record) } delete(records) } for r, i in records { for f, j in r { fmt.printfln("Record %v, field %v: %q", i, j, f) } } } package csv reads and writes comma-separated values (CSV) files. This package supports the format described in [[ RFC 4180; https://tools.ietf.org/html/rfc4180.html ]]

Collection Info

View Source
Collection
core
Path
encoding/csv
Entries
21

Source Files

Constants

1

DEFAULT_RECORD_BUFFER_CAPACITY #

Source
DEFAULT_RECORD_BUFFER_CAPACITY :: 256

Types

5

Reader #

Source
Reader :: Reader

Reader is a data structure used for reading records from a CSV-encoded file The associated procedures for Reader expects its input to conform to RFC 4180.

Writer #

Source
Writer :: Writer

Writer is a data structure used for writing records using a CSV-encoding.

Procedures

14

is_io_error #

Source
@(require_results)
is_io_error :: proc(err: Error, io_err: Error) -> bool {…}

is_io_error checks where an Error is a specific io.Error kind

iterator_last_error #

Source
iterator_last_error :: proc(r: Reader) -> (err: Error) {…}

Get last CSV parse error if we ignored it in the iterator loop for record, row_idx in csv.iterator_next(&r) { ... }

iterator_next #

Source
iterator_next :: proc(r: ^Reader) -> (record: []string, idx: int, err: Error, more: bool) {…}

Returns a record at a time. for record, row_idx in csv.iterator_next(&r) { ... } TIP: If you process the results within the loop and don't need to own the results, you can set the Reader's `reuse_record` and `reuse_record_buffer` to true; you won't need to delete the record or its fields.

read #

Source
@(require_results)
read :: proc(r: ^Reader, allocator := context.allocator) -> (record: []string, err: Error) {…}

read reads a single record (a slice of fields) from r All \r\n sequences are normalized to \n, including multi-line field

read_all #

Source
@(require_results)
read_all :: proc(r: ^Reader, allocator := context.allocator) -> ([][]string, Error) {…}

read_all reads all the remaining records from r. Each record is a slice of fields. read_all is defined to read until an EOF, and does not treat EOF as an error

read_all_from_string #

Source
@(require_results)
read_all_from_string :: proc(input: string, records_allocator := context.allocator, buffer_allocator := context.allocator) -> ([][]string, Error) {…}

read_all reads all the remaining records from the provided input.

read_from_string #

Source
@(require_results)
read_from_string :: proc(input: string, record_allocator := context.allocator, buffer_allocator := context.allocator) -> (record: []string, n: int, err: Error) {…}

read reads a single record (a slice of fields) from the provided input.

reader_init #

Source
reader_init :: proc(reader: ^Reader, r: Stream, buffer_allocator := context.allocator) {…}

reader_init initializes a new Reader from r

reader_init_with_string #

Source
reader_init_with_string :: proc(reader: ^Reader, s: string, buffer_allocator := context.allocator) {…}

reader_init_with_string initializes a new Reader from s

write #

Source
write :: proc(w: ^Writer, record: []string) -> Error {…}

write writes a single CSV records to w with any of the necessarily quoting. A record is a slice of strings, where each string is a single field. If the underlying io.Writer requires flushing, make sure to call io.flush

write_all #

Source
write_all :: proc(w: ^Writer, records: [][]string) -> Error {…}

write_all writes multiple CSV records to w using write, and then flushes (if necessary).

writer_flush #

Source
writer_flush :: proc(w: ^Writer) -> Error {…}

writer_flush flushes the underlying io.Writer. If the underlying io.Writer does not support flush, nil is returned.

Variables

1

reader_error_kind_string #

Source
reader_error_kind_string: [Reader_Error_Kind]string = [Reader_Error_Kind]string{.Bare_Quote = "bare \" in non-quoted field", .Quote = "extra or missing \" in quoted field", .Field_Count = "wrong field count", .Invalid_Delim = "invalid delimiter"}