CSV File Handling
The klyn.io.csv package provides an RFC-4180 style reader and writer. It handles
quoted fields, delimiters, embedded newlines, doubled quotes, and common dialect options.
Imports
import klyn.collections
import klyn.io
import klyn.io.csv
Reading Rows
CSVReader is a forward-only Generator<ArrayList<String>>.
It reads each record on demand instead of loading the whole file. It accepts a file
name, a Path, or any TextReader. File input uses bounded buffers;
memory depends on the current record, not on the total number of rows.
import klyn.collections
import klyn.io
import klyn.io.csv
try reader = CSVReader("contacts.csv", delimiter=';'):
reader.skip(1) # Consume the header record, including any quoted newlines.
for row as ArrayList<String> in reader:
name = row[0]
email = row[1]
print(name + " <" + email + ">")
The cursor cannot be restarted. for closes it on completion,
break, or an exception; try also covers errors before the loop.
Owned files are closed, but a supplied TextReader remains the caller's
responsibility. Quoting errors are raised when reading the affected record, not
when constructing the reader. File encodings are detected from a Unicode BOM,
otherwise UTF-8; pass encoding="utf-16le", for example, when needed.
A reader has no size or indexing API. For small datasets,
readRows() (also named rows()) explicitly collects the
remaining records into a list. It consumes and closes the cursor. Subsequent calls
return an empty list. List operations apply to that result, not to the reader:
rows = CSVReader(StringReader("name\nAda\nAda")).readRows()
assert rows.size == 3ul
assert rows[1][0] == "Ada"
assert rows.indexOf(["Ada"]) == 1
assert rows.lastIndexOf(["Ada"]) == 2
Writing Rows
CSVWriter can buffer output in memory or write directly to a file or text writer.
Use try with file-backed writers so the file is closed deterministically.
import klyn.io.csv
try writer = CSVWriter("contacts.csv", delimiter=';'):
writer.writeRow(["name", "email"])
writer.writeRow(["Ada Lovelace", "ada@example.test"])
writer.writeRow(["Grace Hopper", "grace@example.test"])
For diagnostics or tests, create a buffered writer and call toString().
writeRows() accepts either a list or a generator such as
CSVReader; generators are consumed and closed. The current writer also
retains a text copy for toString() when writing to a file, so its memory
usage, unlike the streaming reader's, grows with the generated output.
writer = CSVWriter(',', '"', Char(), true, "\n")
writer.writeRow(["name", "note"])
writer.writeRow(["Ada, A.", "uses \"quotes\""])
print(writer.toString())
Dialects
The reader and writer expose the usual CSV knobs: delimiter, quote character, escape character, double-quote escaping, initial-space handling, line terminator, and quoting mode.
| Option | Typical use |
|---|---|
delimiter |
Use ';' for semicolon-separated files. |
skipInitialSpace |
Ignore spaces immediately after delimiters. |
quoting |
minimal, all, or none for writer output. |
strict |
Raise CSVException on malformed quoted fields. |