Examples
Real-world patterns showing how ExCSV builds on plain CSV. Examples use version=0.6 — plain, sidecar, ZIP, pack, and JSON.
1. Minimal
Just the header line. Everything else is standard CSV.
name,age,city
Alice,32,Berlin
Bob,28,Tokyo
Carol,45,Lagos Any CSV reader ignores the # line and reads the data normally.
2. Sidecar for plain CSV
Metadata in sales.excsv; rows stay in sales.csv.
sales.csv (data sibling)
Ordinary CSV — any CSV tool reads this.
id,customer,amount
1,Acme Corp,500.00
2,Globex Inc,250.50 See Sidecar. Metadata only — the rows stay in the CSV.
3. Typed columns with constraints
Column schema defines types, validation rules, and display hints.
id,email,score,active
1,alice@example.com,92.5,true
2,bob@example.com,87.3,true
3,carol@example.com,64.0,false Parsers can validate data against pattern, min/max, and required constraints.
4. Tab-delimited with metadata
A TSV export from a database, with provenance metadata.
sku name qty
WDG-001 Widget Pro 1200
WDG-002 Widget Lite 3400
GDG-001 Gadget X 870 The query that produced the file is preserved as #$dql-postgres. The raw text is taken to end of line — SQL syntax preserved as-is.
5. Aggregations
Pre-computed statistics embedded in the file.
region,product,revenue,units
North,Widget,18500.00,520
South,Widget,12000.00,380
North,Gadget,8750.00,210
South,Gadget,5800.00,220
West,Widget,3200.00,120 Aggregation lines use the file's delimiter. Empty fields mean "not applicable" for that column.
6. SQL companions — single dialect via header
Set sql-dialect once, drop the suffix on every #$ line.
id,email,created_at
1,alice@example.com,2026-01-15T09:30:00Z
2,bob@example.com,2026-02-20T14:00:00Z
3,carol@example.com,2026-03-01T11:45:00Z Each #$ddl line is one statement. They execute in file order. #$dql is informational provenance — never executed automatically.
7. SQL companions — multi-dialect
Same data, three flavors of CREATE TABLE. Pick the one matching your target.
id,amount
1,99.99
2,250.00
3,42.50 A consumer targeting mysql executes only the unqualified line and the -mysql line — others are skipped. The unqualified line acts as a portable fallback.
8. Zipped container header
Header of the inner .excsv file inside a sales.excsv.zip archive.
order_id,customer_id,amount
1,42,99.99
2,13,250.00
3,77,42.50 Inside a .excsv.zip, the header records the uncompressed size as original-size. The same prefix is copied into the ZIP comment, so you can preview schema and stats without unzipping. See ZIP.
9. Pack manifest
_manifest.excsv inside sales.excsv.pack.zip (v0.6).
Each table is a folder: schema in _header.excsv, one .col file per column. See Pack.
10. No header row (header=0)
Columns defined by index instead of matching header names.
2026-03-24T10:15:32Z,INFO,Application started
2026-03-24T10:15:33Z,INFO,Connected to database
2026-03-24T10:15:35Z,WARN,Cache miss ratio above threshold
2026-03-24T10:16:01Z,ERROR,Connection timeout on retry 3 With header=0, index is required. name is optional — the first column here is anonymous.
11. Custom attributes (x- prefix)
Application-specific metadata using the x- convention.
id,Full Name,email,segment,ltv
101,Alice Park,alice@acme.co,enterprise|active,12400.00
102,Bob Chen,bob@globex.io,smb,3200.50
103,Carol Diaz,carol@initech.com,enterprise|churned,8750.00 Custom x- attributes are ignored by generic parsers but carry meaning for specific tools. Note how the header row uses title ("Full Name") for columns that have it.
12. JSON form (.excsv.json)
The same document as JSON — for APIs, config, and LLM structured output.
{
"excsv": "0.6",
"csv": { "delim": "comma", "header": true },
"meta": { "source": "hr_db.employees", "grain": "one row per employee" },
"columns": [
{ "index": 0, "name": "id", "type": "int", "role": "id", "unique": true },
{ "index": 1, "name": "name", "type": "string" },
{ "index": 2, "name": "dept", "type": "string", "role": "dimension", "enum": ["Engineering", "Marketing", "Design"] },
{ "index": 3, "name": "salary", "type": "decimal", "unit": "USD", "role": "measure", "agg": "sum" }
],
"aggregates": { "sum": [null, null, null, "285000.00"] },
"rows": 3,
"data": [
[1, "Alice", "Engineering", "120000.00"],
[2, "Bob", "Marketing", "85000.00"],
[3, "Carol", "Design", "80000.00"]
]
} Every # line has a key: the header is csv, #@ is meta, #column is columns (each stored column has index for its position in data rows — a virtual computed column has none), #% is aggregates. decimal values stay strings so they don't turn into floats. Validate against the JSON Schema; see JSON.
13. Quoting (quote=double)
Quote fields that contain the delimiter or embedded double quotes.
name,note
Alice,"She said ""hello"" to everyone"
Bob,"Line1, then more" With quote=double, wrap values in " when they contain commas or quotes; escape a literal quote by doubling (""). Simple values like Alice stay unquoted.
14. Null handling
Default null (empty field) vs custom null marker.
sensor,reading,status
TMP-01,22.5,ok
TMP-02,,offline
TMP-03,NA,ok
TMP-04,19.8,NA Both empty fields and NA are treated as null. Without null=NA, only empty fields would be null.
15. LLM-friendly: grain, enum, role, agg
Semantic hints that let an AI assistant reason about the table without guessing.
order_id,status,amount,balance,created_at
1,completed,500.00,1200.00,2026-01-15T09:30:00Z
2,completed,300.50,900.00,2026-02-20T14:00:00Z
3,pending,200.00,700.00,2026-03-01T11:45:00Z
4,cancelled,50.00,650.00,2026-03-10T16:20:00Z #@grain states what one row is. enum gives the closed value domain for status. role tells a consumer how to use each column — group by dimension, aggregate measure, never sum an id — and agg flags additivity: amount sums, but balance (agg=avg) must not be summed across time. All are advisory hints; none change how a plain CSV reader sees the data.