Skip to content
Jennifer Programming Language

csv API reference

RFC 4180 comma-separated values: parse text into rows of fields and format rows back into text, with a quoting-aware hand-written scanner. Pure Jennifer - no Go, no system library. The delimiter is configurable, so the same code reads and writes TSV and other single-character-separated formats. Records separate on LF or CRLF (a bare CR outside quotes also ends a record); a field is quoted with " when it contains the delimiter, a quote, or a newline, and an embedded quote doubles to "". format() joins records with LF and adds no trailing newline, so parse(format(rows)) round-trips the data.

Import with import "csv.j" as csv;. See the csv guide for prose and examples.

Functions

csv.closeReader(reader as Reader)

Close a streaming reader (closes the underlying file handle).

Parameters

  • reader {Reader} - the reader

csv.closeWriter(writer as Writer)

Close a streaming writer (closes the underlying file handle).

Parameters

  • writer {Writer} - the writer

csv.dialect(delimiter as string)

A Dialect with the given delimiter and the standard defaults: quote ", no comment prefix, no trimming. Set the other fields to customise.

Parameters

  • delimiter {string} - the single-character field delimiter

Returns {Dialect} - the dialect

csv.format(rows as list of list of string)

Join rows into standard comma-delimited CSV. Not safe for a spreadsheet target - use formatSafe when the output may be opened in Excel / Sheets (see formatWith on the CWE-1236 formula-injection risk).

Parameters

  • rows {list of list of string} - the rows of fields to format

Returns {string} - the formatted comma-separated text

csv.formatDialect(rows as list of list of string, d as Dialect)

Format rows under a Dialect (custom delimiter and quote character). Records are joined with LF and no trailing newline, like formatWith. The comment and trim fields are parse-only and ignored here.

Parameters

  • rows {list of list of string} - the rows of fields to format
  • d {Dialect} - the dialect controlling delimiter/quote

Returns {string} - the formatted text

csv.formatSafe(rows as list of list of string)

Injection-safe standard comma-delimited CSV (see formatSafeWith). The export-to-spreadsheet path; prefer it over format for spreadsheet targets.

Parameters

  • rows {list of list of string} - the rows of fields to format

Returns {string} - the formatted, injection-neutralised comma-separated text

csv.formatSafeWith(rows as list of list of string, delim as string)

Like formatWith, but neutralises spreadsheet formula injection (CWE-1236) before quoting: any field whose first character is =, +, -, @, a tab, or a CR is prefixed with a single apostrophe so Excel / Google Sheets import it as literal text instead of executing it. Use this - not formatWith - for any CSV a spreadsheet will open.

Parameters

  • rows {list of list of string} - the rows of fields to format
  • delim {string} - the single-character field delimiter

Returns {string} - the formatted, injection-neutralised text

csv.formatWith(rows as list of list of string, delim as string)

Join rows into text with a single-character delimiter, quoting each field as needed. Records are separated by LF with no trailing newline.

Not safe for a spreadsheet target. A field beginning = + - @ (or a tab / CR) is a formula that Excel / Google Sheets will execute on open (CWE-1236). If the output is opened as a spreadsheet, use formatSafe / formatSafeWith, which neutralise such fields.

Parameters

  • rows {list of list of string} - the rows of fields to format
  • delim {string} - the single-character field delimiter

Returns {string} - the formatted delimiter-separated text

csv.fromRecords(header as list of string, records as list of map of string to string)

The inverse of toRecords: emit the header row followed by one row per record, taking fields in header order (a key absent from a record writes ""). The explicit header fixes the column order, which map iteration does not.

Parameters

  • header {list of string} - the column names, in output order
  • records {list of map of string to string} - the records to emit

Returns {list of list of string} - the header row followed by one row per record

csv.parse(s as string)

Scan standard comma-delimited CSV.

Parameters

  • s {string} - the CSV text to parse

Returns {list of list of string} - the parsed rows of fields

csv.parseDialect(text as string, d as Dialect)

Parse CSV text under a Dialect: custom delimiter and quote, comment-line skipping, and optional unquoted-field trimming. Quoted fields keep their content (including whitespace and embedded newlines) verbatim.

Parameters

  • text {string} - the CSV text to parse
  • d {Dialect} - the dialect controlling delimiter/quote/comment/trim

Returns {list of list of string} - the parsed rows of fields

csv.parseWith(s as string, delim as string)

Scan CSV text with a single-character delimiter and return its rows, each a list of string fields. A quoted field may span the delimiter, newlines, and doubled quotes; an empty input yields no rows.

Parameters

  • s {string} - the CSV text to parse
  • delim {string} - the single-character field delimiter

Returns {list of list of string} - the parsed rows of fields

csv.readRow(reader as Reader)

Read one complete CSV record from the reader, returning its fields. A record whose quoted field spans physical lines is read to completion (further lines are pulled until the quotes balance). Returns the empty list [] at end-of-file (guard the loop with readerEof) and for a blank line.

Parameters

  • reader {Reader} - the reader

Returns {list of string} - the record's fields, or [] at EOF / on a blank line

csv.reader(file as fs.File)

Wrap an open, read-mode fs.File as a comma-delimited streaming reader.

Parameters

  • file {fs.File} - an open read-mode file handle

Returns {Reader} - the reader

csv.readerEof(reader as Reader)

Whether the reader has reached end-of-file. Loop while (not readerEof($r)).

Parameters

  • reader {Reader} - the reader

Returns {bool} - true once no further record remains

csv.readerWith(file as fs.File, delim as string)

Wrap an open, read-mode fs.File as a streaming reader with a custom single-character delimiter.

Parameters

  • file {fs.File} - an open read-mode file handle
  • delim {string} - the single-character field delimiter

Returns {Reader} - the reader

csv.toRecords(rows as list of list of string)

Treat the first row as a header and map each later row into a map of string to string keyed by the header names. Every record carries every header key (a short row fills missing fields with ""); fields past the header width are dropped. An empty input yields no records.

Parameters

  • rows {list of list of string} - the rows, with the first as the header

Returns {list of map of string to string} - one record per non-header row

csv.writeRow(writer as Writer, fields as list of string)

Append one record to the writer: the fields, quoted as needed, followed by LF.

Parameters

  • writer {Writer} - the writer
  • fields {list of string} - the record's fields

csv.writer(file as fs.File)

Wrap an open write/append-mode fs.File as a comma-delimited streaming writer.

Parameters

  • file {fs.File} - an open write- or append-mode file handle

Returns {Writer} - the writer

csv.writerWith(file as fs.File, delim as string)

Wrap an open write/append-mode fs.File as a streaming writer with a custom single-character delimiter.

Parameters

  • file {fs.File} - an open write- or append-mode file handle
  • delim {string} - the single-character field delimiter

Returns {Writer} - the writer

Structs

csv.Dialect

A CSV dialect: the field delimiter, the quote character, an optional comment-line prefix (a physical line whose record starts with it is skipped on parse; "" disables comments), and whether unquoted fields are whitespace- trimmed on parse. Build one with dialect(delimiter) for the common defaults.

FieldTypeDescription
delimiterstringthe single-character field delimiter
quotestringthe quote character (default ")
commentstringthe comment-line prefix, or "" for none
trimbooltrim leading/trailing whitespace from unquoted fields

csv.Reader

A streaming CSV reader over an open fs.File, for tables too large to hold in memory. The wrapped file is a handle - it shares its read position across value copies - so successive readRow calls advance the same stream.

FieldTypeDescription
filefs.Filethe underlying open file handle
delimstringthe single-character field delimiter

csv.Writer

A streaming CSV writer over an open fs.File. Each writeRow call appends one quoted-as-needed record terminated by LF, so a large table is written without building the whole text in memory.

FieldTypeDescription
filefs.Filethe underlying open write/append-mode file handle
delimstringthe single-character field delimiter