PackageTrack
Sign in Get early access

csv_plus

Fast, complete CSV parser for Dart. Encode, decode, stream, query, and validate CSV data with automatic type inference and zero dependencies.

1.3.0 5.0K downloads/mo #3843 most downloaded on pub.dev almasumdev/csv_plus

What this package is like to depend on

Last release today

24 Aug 2026

Release timing varies

gaps range from 2 weeks to 3 months

Nearly every release is documented

notes for 8 of 8 stable releases

Nothing withdrawn

no release was ever pulled

4 months old

8 releases · first in 2026

8 releases in the last 12 months

see the full history below

Release timeline

8 releases · Apr 2026 to Aug 2026
Release Pre-release

Releases

latest 8
  1. 1.3.0 24 Aug 2026
    Release notes

    CsvConfig(parseDates: true) turns a field in ISO-8601 form into a real
    DateTime during a typed decode, across decode, decodeToTable, decodeToMaps,
    the streaming CsvDecoder, and bindBytes. Off by default.

    Every date and time field is range-checked before parsing, so an impossible
    value stays text instead of becoming the wrong date: DateTime.parse rolls
    2024-13-45 over to 14 February 2025, and this does not. Ambiguous locale
    formats, unpunctuated runs such as 20240131, and quoted fields all stay text.

    Closes the only entry in the README's Limitations list. Adds a docs page at
    /csv-dates and corrects the type-inference FAQ, which named a flag
    (inferTypes) that does not exist.

    Open source →
    Release notes

    Opt-in ISO-8601 date and date-time inference. Additive and backward-compatible.

    New

    • CsvConfig(parseDates: true) turns a field in ISO-8601 form into a real DateTime during a typed decode, instead of leaving it as text. It applies everywhere inference does: decode, decodeToTable, decodeToMaps, the streaming CsvDecoder, and bindBytes. Off by default, so nothing changes for existing code.
    • A value must start with YYYY-MM-DD; a time part may follow after a T or a space, with optional fractional seconds and a Z or numeric offset. A value with no offset reads as local time, one with an offset as UTC. Ambiguous locale formats such as 03/04/2024 stay text, as do quoted fields and unpunctuated runs such as 20240131.
    • Every date and time field is range-checked before parsing, so an impossible value stays text instead of silently becoming the wrong date. DateTime.parse rolls 2024-13-45 over to 14 February 2025; csv_plus does not.
    • FastDecoder.tryParseIsoDateTime exposes the same strict parser, and FastDecoder.inferType takes an optional parseDates flag.

    A DateTime encodes back to a form that decodes to the same value, so a decode/encode round trip is lossless in both local and UTC.

    Open source →
  2. 1.2.1 23 Aug 2026
    Release notes

    The IndexNow key file is named after the key, so building before the real
    key was set left a PLACEHOLDER.txt behind. The .firebase cache is local
    deploy state and should never have been tracked.

    Open source →
    Release notes

    Changed

    • Added a documentation website at https://csv-plus.web.app, with guides for parsing, reading and writing CSV, headers, type inference, querying and grouping, JSON conversion, schemas, delimiters, and large files. Linked from the package page via the new documentation field.
    Open source →
  3. 1.2.0 25 Jul 2026
    Release notes

    Add CsvSchema.coerce, CsvTable.coerce, and CsvCodec.decodeWithSchema to
    convert each column's values to the type declared on its CsvColumnDef
    (int, double, num, bool, String, DateTime). A column with no schema entry
    or a null type is left unchanged; CsvTable.coerce returns a copy and never
    mutates the source.

    Coercion throws CsvParseException (carrying the 0-based row and column) on
    a value that cannot convert, or a null in a column declared nullable:false;
    a null in a nullable column stays null. Completes the schema story: it
    could already validate types, and can now coerce them.

    Open source →
    Release notes

    Per-column type coercion driven by CsvSchema. Additive and backward-compatible.

    New

    • CsvSchema.coerce(headers, rows), CsvTable.coerce(schema), and CsvCodec.decodeWithSchema(input, schema) convert each column's values to the type declared on its CsvColumnDef (int, double, num, bool, String, or DateTime). A column with no schema entry, or a null type, is left unchanged; CsvTable.coerce returns a copy and never mutates the source.
    • Coercion throws CsvParseException (carrying the 0-based row and column) when a value cannot be converted, or when a null appears in a column declared nullable: false; a null in a nullable column stays null. This completes the schema story: CsvSchema could already validate types, and can now coerce them.
    Open source →
  4. 1.1.0 16 Jul 2026
    Release notes

    Add three decode-only CsvConfig options plus a codec convenience:

    • comment: drop comment-prefixed lines, detected only at the start of a
      line so a marker inside a quoted or mid-field value stays content
    • skipRows: skip leading rows before the header row (a preamble)
    • maxRows: cap the returned data rows; the batch decoders stop early and
      the streaming decoder stops emitting
    • CsvCodec.decodeToMaps: decode straight to header-keyed maps

    All three options apply across every decode path (batch typed, strings,
    flexible, the typed decoders, table, maps, and the streaming decoder) and
    are held to identical output by the conformance suite, which splits input
    at every chunk boundary. Closes the comment-skipping and row-windowing
    roadmap items.

    Open source →
    Release notes

    Comment-line skipping, row windowing, and a header-keyed map decode. All additions are backward-compatible: existing calls behave exactly as before.

    New

    • CsvConfig(comment: '#') drops comment lines while decoding. The marker is matched only at the very start of a line, so a # inside a quoted field or mid-field is ordinary content. The marker is a single character; comment lines never count toward skipRows.
    • CsvConfig(skipRows: n) skips leading rows before the header row is read, for a preamble sitting above the real table.
    • CsvConfig(maxRows: n) caps the number of data rows returned (the header is not counted); the batch decoders stop reading once the limit is reached and the streaming decoder stops emitting.
    • CsvCodec.decodeToMaps decodes straight to a List<Map<String, dynamic>> keyed by header name, a shortcut for decodeToTable(input).toMaps().

    All three config options apply across every decode path (decode, decodeStrings, decodeFlexible, the typed decoders, decodeToTable, decodeToMaps, and the streaming CsvDecoder), and are held to identical output by the conformance suite that splits input at every chunk boundary.

    Open source →
  5. 1.0.1 10 Jul 2026
    Release notes

    Documentation and metadata only; no library or API changes.

    • Reworked the README (clearer structure, added the logo screenshot, and broader keyword coverage) and refined the pub.dev topics for discoverability.
    • Switched the head-to-head benchmark to compare against serial_csv in place of fast_csv.
    Open source →
  6. 1.0.0 10 Jul 2026
    Release notes

    docs: rewrite README to the canonical structure; migrate repo URLs to…

    Open source →
    Release notes

    First stable release: one documented parsing semantics across every decode path, streaming you can trust, data-loss guards on type inference, and public benchmark receipts. The API is now frozen under semantic versioning.

    One parsing semantics (breaking behavior alignments)

    The batch decoder, string decoder, and streaming decoder previously disagreed on edge cases. All paths now produce identical output, enforced by a conformance suite that also splits input at every chunk boundary (test/conformance_test.dart).

    • An empty line reads as a row with one empty field ([''], or [null] with typing), per RFC 4180 and matching csv 8 and fast_csv. With skipEmptyLines (default), rows of a single empty field are dropped; rows of several empty fields (,,) are now always kept (previously decodeStrings dropped them).
    • Text after a closing quote is appended to the field, so "a"x reads ax (Excel behavior). Previously the batch decoder produced an extra cell and the streaming decoder swallowed the following delimiter.
    • With hasHeader, the header row is read as raw strings on every path: a header cell 01 stays 01 (previously typed then stringified to 1), and decoderTransform is not applied to it.
    • Quoted fields are never type-inferred on any path.

    Type inference guards (data safety)

    FastDecoder.inferType is now the single shared inference used by all typed paths, with guards against silent corruption:

    • Leading zeros (007), leading plus (+1), and surrounding whitespace stay text (previously ' 42' typed differently per path).
    • Digit runs longer than 15 stay text on every platform, keeping VM and web results identical (web ints lose precision past 2^53).
    • Values that would parse to a non-finite double (1e999) stay text.

    Typed decoders no longer invent data (breaking)

    • decodeIntegers / decodeDoubles / decodeBooleans throw CsvParseException (with row and column) on invalid cells instead of coercing them; empty cells throw unless an explicit emptyAs: fill is passed (previously empty became 0 / 0.0 and any non-true value became false).
    • decodeBooleans truth table is documented and case-insensitive: true/1 and false/0.
    • decodeFlexible uses config.quoteCharacter when restoring an unmatched quote (previously hardcoded "), and reads empty fields as '' instead of null when typing is off.

    Streaming you can trust

    • CsvDecoder.bind and CsvEncoder.bind honor downstream backpressure (pause/resume/cancel propagate to the source), so a slow consumer no longer buffers the whole input in memory, and the output stream closes after an upstream error instead of hanging.
    • Multi-character delimiters split across chunk boundaries now parse correctly (previously they became field text).
    • New CsvDecoder.bindBytes / CsvEncoder.bindBytes for UTF-8 byte streams without manual utf8 wiring.
    • CsvFile.writeStream closes the file even when the source stream errors.

    New: strict mode

    CsvConfig(strict: true) throws CsvParseException with row and column on structurally malformed input (text after a closing quote, unterminated quote) instead of recovering. Lenient stays the default.

    Fixed

    • decodeWithHeaders parsed the entire input twice; it is now single pass and roughly twice as fast (fastest in the ecosystem on this workload, previously the single lost benchmark).
    • CsvTable.map handed live row lists to its transform, so writing through the row mutated the source table. The transform now receives a copy; the source is never modified.
    • Delimiter autodetect no longer misreads single-column text containing semicolons as two columns: a candidate must appear on every sampled line to qualify (csv 8 still has this failure).
    • CsvTable.parse headers are raw strings (01 stays 01).
    • All table sorts are stable, and nulls sort last in both directions. Mixed-type columns sort numbers before string look-alikes instead of comparing "10" < "9" lexicographically.
    • distinct() keys are type-aware (1, 1.0, and "1" are distinct) and immune to separator collisions in string content.
    • encodeGeneric<String> quotes strings containing delimiters instead of producing corrupt CSV; QuoteMode.always writes null as "".
    • Batch and streaming encoders share one cell-writing implementation.

    Changed

    • ColumnDef is renamed CsvColumnDef (a deprecated typedef keeps old code compiling).
    • DelimiterDetector left the default csv_plus.dart namespace; import package:csv_plus/decoder.dart to use it directly.
    • CsvTable documents its mutation rule: table-returning methods copy, void methods mutate in place. New stable sortedBy() returns a sorted copy.
    • Releases are gated: the publish workflow now runs format, analyze, tests, and a publish dry-run before tagging or publishing, and CI runs a stable + minimum SDK matrix plus wasm and pana jobs.

    Benchmarks

    Fastest on every measured workload (decode, typed decode, autodetect, quote-heavy, encode, decodeWithHeaders) against csv 8.0.0, fast_csv 0.2.11, and serial_csv 0.5.2, on JIT and AOT. The reproducible harness and full tables live in benchmark/compare/.


    Open source →
  7. 0.0.2 15 Apr 2026
    Release notes
    • Topics: csv, csv-parser, serialization, data-processing, file-handling
    • Changelog: added 0.0.2 entry for docs, CI, and meta changes
    • Version bump 0.0.1 → 0.0.2
    Open source →
    Release notes

    Documentation

    • Redesigned README with hero layout, badges, feature table, and quick start examples
    • Added 8 mini-library files for dartdoc sidebar navigation (core, codec, encoder, decoder, table, query, transform, io)
    • Enhanced barrel export lib/csv_plus.dart with library modules reference

    Meta

    • Added MIT LICENSE file
    • SEO-optimized pubspec description and topics for pub.dev
    • Added CI workflow (analyze, format, test on PRs)
    • Added publish workflow (auto-tag + publish to pub.dev)

    Open source →
  8. 0.0.1 15 Apr 2026
    Release notes

    chore: update README version, add CI workflows

    Open source →
    Release notes

    Core

    • CsvConfig: immutable configuration with presets: CsvConfig(), .excel(), .tsv(), .pipe()
    • CsvConfig.copyWith(): create modified copies
    • QuoteMode enum: necessary, always, strings
    • CsvException, CsvParseException, CsvValidationException: typed error hierarchy

    Encoding

    • FastEncoder: high-performance batch encoder with encode(), encodeStrings(), encodeGeneric<T>(), encodeMap()
    • CsvEncoder: streaming encoder as StreamTransformer with bind(), convert(), startChunkedConversion()
    • CsvEncoder.encodeField(): static helper for single-field quoting
    • codeUnit-based _needsQuoting() for multi-char delimiter support

    Decoding

    • FastDecoder: byte-level batch decoder with codeUnits parsing, labeled-loop control flow, first-byte type inference
    • Decode variants: decode(), decodeStrings(), decodeFlexible(), decodeIntegers(), decodeDoubles(), decodeBooleans()
    • CsvDecoder: chunked state-machine streaming decoder with bind(), convert(), startChunkedConversion()
    • Handles chunk boundaries splitting mid-field, mid-escape, mid-CRLF
    • DelimiterDetector: frequency/consistency scoring across candidates [, ; \t |], BOM strip, sep= hint

    Facade

    • CsvCodec: main API with all decode/encode methods, presets, auto-detection
    • CsvCodec.decodeToTable(), decodeMap(), encodeMap()
    • CsvCodec.decoder / encoder: streaming transformer getters
    • CsvCodecAdapter: Codec<List<List<dynamic>>, String> for dart:convert pipelines and .fuse()
    • csvPlus, csvExcel, csvTsv: global convenience instances

    CsvTable (50+ methods)

    • Constructors: CsvTable(), .withHeaders(), .fromData(), .fromMaps(), .parse(), .empty()
    • Access: operator [], cell(), cellByName(), setCell(), setCellByName(), column(), columnAt(), getColumn(), getColumnAt()
    • Row ops: addRow(), addRowFromMap(), addRows(), insertRow(), removeRow(), removeWhere()
    • Column ops: addColumn(), insertColumn(), removeColumn(), removeColumnAt(), renameColumn(), reorderColumns()
    • Query: where(), firstWhere(), any(), every(), range(), take(), skip(), distinct()
    • Sort: sortBy(), sortByIndex(), sortByMultiple(), sort()
    • Transform: transformColumn(), map(), fold<T>()
    • Aggregate: count(), sum(), avg(), min(), max(), groupBy()
    • Export: toList(), toMaps(), toCsv(), toString(), toFormattedString(), copy()
    • Validation: validate(), conformsTo(), inferSchema()

    CsvRow

    • Dual-mode access: row[0] (int) and row['name'] (String)
    • set(), headerMap, hasHeaders, headers, containsHeader(), toMap(), getHeaderName(), toString()

    CsvColumn

    • Column descriptor with name, index, values, inferredType, nonNullCount, nullCount, uniqueCount

    CsvSchema & ColumnDef

    • Schema definition with columns, allowExtraColumns, allowMissingColumns
    • CsvSchema.infer(): infer types and nullability from data
    • validate(): check required columns, types, nullability, patterns, custom validators
    • ColumnDef with name, type, required, nullable, pattern, validator

    CsvFile (dart:io)

    • Static methods: read(), readSync(), stream(), write(), writeSync(), writeRows(), writeStream(), append()
    • Uses utf8.decoder for stream operations
    • Isolated in io/csv_file.dart: core library stays platform-independent
    Open source →

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive