{"id":32309272,"url":"https://github.com/close2/csv","last_synced_at":"2026-02-22T01:38:59.537Z","repository":{"id":21372499,"uuid":"24689841","full_name":"close2/csv","owner":"close2","description":"A dart csv to list codec / converter","archived":false,"fork":false,"pushed_at":"2026-02-10T15:10:46.000Z","size":207,"stargazers_count":99,"open_issues_count":6,"forks_count":25,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-02-10T18:59:36.227Z","etag":null,"topics":["csv-converter","csv-parser","dart"],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/close2.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-10-01T18:20:49.000Z","updated_at":"2026-02-10T15:43:53.000Z","dependencies_parsed_at":"2023-10-16T16:47:38.625Z","dependency_job_id":"b8efe2a6-552f-466b-be73-e6b6144c7715","html_url":"https://github.com/close2/csv","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/close2/csv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/close2%2Fcsv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/close2%2Fcsv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/close2%2Fcsv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/close2%2Fcsv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/close2","download_url":"https://codeload.github.com/close2/csv/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/close2%2Fcsv/sbom","scorecard":{"id":292128,"data":{"date":"2025-08-11","repo":{"name":"github.com/close2/csv","commit":"a6856fb7e90684518378f192d0d6da0bc5c21875"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.3,"checks":[{"name":"Code-Review","score":5,"reason":"Found 7/14 approved changesets -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/close2/csv/test.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/close2/csv/test.yml/master?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 27 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T18:31:19.514Z","repository_id":21372499,"created_at":"2025-08-17T18:31:19.515Z","updated_at":"2025-08-17T18:31:19.515Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29703227,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T23:35:04.139Z","status":"ssl_error","status_checked_at":"2026-02-21T23:35:03.832Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csv-converter","csv-parser","dart"],"created_at":"2025-10-23T08:20:43.243Z","updated_at":"2026-02-22T01:38:59.532Z","avatar_url":"https://github.com/close2.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# csv\n\nA high-quality, best-practice CSV library for Dart, inspired by PapaParse but built with Dart idioms in mind.\n\n## Upgrading from Version 6\nVersion 7 is a complete rewrite and introduces breaking changes.\nIf you rely on the specific flexibility of version 6 (e.g., complex eol handling not supported here),\nplease consult [doc/README-v6.md](doc/README-v6.md) and continue using version 6.\n\n## Features\n\n- **Darty API**: Fully implements `Codec` and `Converter` interfaces from `dart:convert`.\n- **Easy Excel Compatibility**: Built-in support for Excel-compatible CSVs (UTF-8 BOM, `;` separator, `\\r\\n` line endings).\n- **Auto-detection**: Smartly detects delimiters and line endings.\n- **Robust Parsing**: Handles quoted fields, escaped quotes, and even malformed CSVs graciously (similar to PapaParse).\n- **Performance**: Optimized for speed and low memory usage.\n- **Dynamic Typing**: Optional automatic parsing of numbers and booleans (similar to PapaParse).\n\n\n### Delimiters\n\nThe `CvCodec` and `CsvDecoder` support:\n*   **Field Delimiters**: Can be single or multi-character strings (e.g., `,`, `::`, `|`).\n*   **Quote Character**: Must be a **single character**. Defaults to `\"`.\n*   **Escape Character**: Must be a **single character** (if provided). Defaults to the quote character.\n*   **Line Delimiters**: The decoder automatically handles `\\r`, `\\n`, and `\\r\\n`. The encoder allows specifying a custom `lineDelimiter` (defaults to `\\r\\n`).\n\n## ⚠️ Important: Line Endings \u0026 Windows\n\nThe default line delimiter is `\\r\\n` (CRLF) as specified by RFC 4180.\n\n**Be careful on Windows!**\nIf you write the CSV string directly to a file using certain methods (like `File.writeAsString` without specifying strict options or redirecting `stdout`), Windows file handling might automatically convert `\\n` to `\\r\\n`. Since the CSV already contains `\\r\\n`, this can result in double carriage returns: `\\r\\r\\n`.\n\nTo avoid this, either:\n1.  **Use `\\n` as the line delimiter:**\n    ```dart\n    final codec = CsvCodec(lineDelimiter: '\\n');\n    final csvString = codec.encode(data);\n    ```\n2.  **Use a binary writer** (e.g., `File.openWrite()`) which writes bytes exactly as they are.\n\n## Usage\n\n### Simple Example\n\n```dart\nimport 'package:csv/csv.dart';\n\nvoid main() {\n  final data = [\n    ['Name', 'Age', 'City'],\n    ['Alice', 30, 'New York'],\n    ['Bob', 25, 'London'],\n  ];\n\n  // Encode\n  final String csvString = csv.encode(data);\n  print(csvString);\n\n  // Decode\n  final List\u003cList\u003cdynamic\u003e\u003e decodedData = csv.decode(csvString);\n  print(decodedData);\n}\n```\n\n### Excel Compatible CSV\n\nExcel often requires a UTF-8 BOM and `;` as a separator to open files correctly in certain locales.\n\n```dart\nimport 'package:csv/csv.dart';\n\nvoid main() {\n  final data = [\n    ['Header1', 'Header2'],\n    ['Value 1', 'Value 2'],\n  ];\n\n  // Use the built-in excel codec\n  final String excelCsv = excel.encode(data);\n  \n  // This automatically adds the BOM and uses ';' as delimiter\n}\n```\n\n### Custom Configuration\n\n```dart\nimport 'package:csv/csv.dart';\n\nvoid main() {\n  final myCodec = CsvCodec(\n    fieldDelimiter: '\\t',\n    lineDelimiter: '\\n',\n    quoteMode: QuoteMode.strings, // Only quote strings, not numbers\n    escapeCharacter: '\\\\',       // Use backslash for escaping\n  );\n  \n  final encoded = myCodec.encode([['a', 1, true], ['b', 2.5, false]]);\n  // Output: \"a\",1,true\\n\"b\",2.5,false\n}\n```\n\n### Dynamic Typing\n\nAutomatically convert values that look like numbers or booleans into their respective Dart types.\n\n\u003e [!NOTE]\n\u003e Enabling `dynamicTyping` adds a small performance overhead (approx. 15% in benchmarks). For maximum performance on large files where you know the schema, using a manual `decoderTransform` or processing rows after decoding is faster.\n\n```dart\nimport 'package:csv/csv.dart';\n\nvoid main() {\n  final input = 'Name,Age,Active\\nAlice,30,true';\n  \n  // With dynamic typing enabled\n  final codec = CsvCodec(dynamicTyping: true);\n  final rows = codec.decode(input);\n  \n  print(rows[0][1].runtimeType); // int (30)\n  print(rows[0][2].runtimeType); // bool (true)\n}\n```\n\n### Advanced: Field Transformations\n\nYou can use the `encoderTransform` and `decoderTransform` hooks to process fields based on their value, column index, or header name to for example trim text, change decimal separators or format dates.\n\n```dart\nimport 'package:csv/csv.dart';\n\nvoid main() {\n  final customCodec = CsvCodec(\n    fieldDelimiter: ';',\n    parseHeaders: true, // Required if you want 'header' name in the transform\n    decoderTransform: (value, index, header) {\n      // Change column 3 (index 2) to uppercase\n      if (index == 2) return value.toUpperCase();\n      \n      // Convert 'Age' column to int\n      if (header == 'Age') return int.tryParse(value) ?? value;\n      \n      return value;\n    },\n  );\n\n  final input = 'Name;City;Age\\nAlice;London;30';\n  final decoded = customCodec.decode(input);\n  \n  print(decoded[0]['Age']);   // 30 (as int)\n  print(decoded[0]['City']);  // LONDON\n}\n```\n\n### Automated Delimiter Detection (including sep=;)\n\nThe library automatically detects common delimiters (`,`, `;`, `\\t`, `|`). It also respects the `sep=;` header common in some Excel-exported CSV files.\n\n```dart\nfinal decoded = csv.decode('sep=;\\r\\nA;B;C');\n// Result: [['A', 'B', 'C']]\n```\n\n### Map-like Row Access\n\nIf you want to access values by their header names, use the `parseHeaders` option. It returns `CsvRow` objects which behave like both a `List` and a `Map`.\n\n```dart\nimport 'package:csv/csv.dart';\n\nvoid main() {\n  final fileContents = 'id,name\\n1,Alice\\n2,Bob';\n  final codec = CsvCodec(parseHeaders: true);\n  \n  final rows = codec.decode(fileContents);\n  \n  // Access by header name\n  print(rows[0]['name']); // Alice\n  \n  // Still accessible by index\n  print(rows[0][1]);      // Alice\n  \n  // The first row of the file was used for headers and is not in the list.\n}\n```\n\n### Stream Transformation (Read-Modify-Write)\n\nYou can use `fuse` to combine the encoder and decoder, or simply chain transformations to process large files efficiently.\n\n```dart\nimport 'dart:convert';\nimport 'dart:io';\nimport 'package:csv/csv.dart';\n\nvoid main() async {\n  final input = File('input.csv');\n  final output = File('output.csv');\n\n  await input.openRead()\n      .transform(utf8.decoder)\n      .transform(csv.decoder)\n      .map((row) {\n        // Modify the row\n        row.add('Processed');\n        return row;\n      })\n      .transform(csv.encoder)\n      .transform(utf8.encoder)\n      .pipe(output.openWrite());\n}\n```\n\n### Fusing Codecs\n\nYou can also fuse the `csv.encoder` and `csv.decoder` (or any other compatible codecs) to create a new codec.\n\n```dart\nimport 'dart:convert';\nimport 'package:csv/csv.dart';\n\nvoid main() {\n  // Create a codec that converts List\u003cList\u003e -\u003e String -\u003e List\u003cList\u003e\n  // Ideally this is an identity transformation (Round Trip).\n  final fused = csv.encoder.fuse(csv.decoder);\n  \n  final data = [['a', 'b'], ['c', 'd']];\n  final result = fused.convert(data);\n  print(result); // [['a', 'b'], ['c', 'd']]\n}\n```\n\n### Advanced Fusing: Processing Pipeline\n\nYou can create a `Codec` that reads a CSV string, processes the data, and outputs a new CSV string by fusing the decoder, a custom processor, and the encoder.\n\n```dart\nimport 'dart:convert';\nimport 'package:csv/csv.dart';\n\n// A simple converter that adds a column to every row.\nclass AddColumnConverter extends Converter\u003cList\u003cList\u003cdynamic\u003e\u003e, List\u003cList\u003cdynamic\u003e\u003e\u003e {\n  @override\n  List\u003cList\u003cdynamic\u003e\u003e convert(List\u003cList\u003cdynamic\u003e\u003e input) {\n    return input.map((row) =\u003e [...row, 'Processed']).toList();\n  }\n}\n\nvoid main() {\n  final processor = AddColumnConverter();\n\n  // Create a pipeline: CSV String -\u003e List\u003cList\u003e -\u003e Modified List\u003cList\u003e -\u003e CSV String\n  \n  // Let's create a \"Processing Codec\" that takes String and returns String (CSV -\u003e CSV)\n  // We start with the decoder (String -\u003e List)\n  // Fuse with processor (List -\u003e List)\n  // Fuse with encoder (List -\u003e String)\n  \n  final sanitizingCodec = csv.decoder.fuse(processor).fuse(csv.encoder);\n\n  final inputCsv = 'Name,Age\\nAlice,30';\n  final outputCsv = sanitizingCodec.convert(inputCsv);\n\n  print(outputCsv);\n  // Output:\n  // Name,Age,Processed\n  // Alice,30,Processed\n}\n```\n\n\n## PapaParse Features\n\nThis library incorporates many good ideas from PapaParse, such as:\n- Handling misplaced quotes gracefully.\n- Auto-detecting delimiters based on frequency and consistency.\n- Handling various line ending styles automatically in the decoder.\n- Support for `sep=` headers.\n- Header Parsing: Efficiently mapping headers to row indices (similar to `header: true` in PapaParse).\n\n## Installation\n\nAdd this to your `pubspec.yaml`:\n\n```yaml\ndependencies:\n  csv: ^7.0.0\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclose2%2Fcsv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclose2%2Fcsv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclose2%2Fcsv/lists"}