Skip to main content
On this page

@std/csv

Overview Jump to heading

Reads and writes comma-separated values (CSV) files.

Parsing CSV

import { parse } from "@std/csv/parse";
import { assertEquals } from "@std/assert";

const string = "a,b,c\nd,e,f";

// Parse as array of arrays (default)
assertEquals(parse(string, { skipFirstRow: false }), [["a", "b", "c"], ["d", "e", "f"]]);

// Parse csv file with headers into array of objects
assertEquals(parse(string, { skipFirstRow: true }), [{ a: "d", b: "e", c: "f" }]);

// Parse with custom column names
assertEquals(parse(string, { columns: ["x", "y", "z"] }), [
  { x: "a", y: "b", z: "c" },
  { x: "d", y: "e", z: "f" }
]);

// Parse tab-separated values
const tsvString = "name\tage\tcity\njohn\t30\tnew york\nmary\t25\tlos angeles";
assertEquals(parse(tsvString, { separator: "\t", skipFirstRow: true }), [
  { name: "john", age: "30", city: "new york" },
  { name: "mary", age: "25", city: "los angeles" }
]);

// Parse a CSV file which has comments
const csvWithComments = "# This is a comment\nname,age,city\n# Another comment\njohn,30,new york\nmary,25,los angeles";
assertEquals(parse(csvWithComments, { comment: "#", skipFirstRow: true }), [
  { name: "john", age: "30", city: "new york" },
  { name: "mary", age: "25", city: "los angeles" }
]);

Parsing CSV from a Stream

import { CsvParseStream } from "@std/csv/parse-stream";
import { assertEquals } from "@std/assert";

// Parse from a stream (useful for large files)
const source = ReadableStream.from([
  "name,age,city\n",
  "john,30,new york\n",
  "mary,25,los angeles\n"
]);

const csvStream = source
  .pipeThrough(new CsvParseStream({ skipFirstRow: true }));

const records = await Array.fromAsync(csvStream);
assertEquals(records, [
  { name: "john", age: "30", city: "new york" },
  { name: "mary", age: "25", city: "los angeles" }
]);

// Or process records one by one
// for await (const record of csvStream) {
//   console.log(record);
// }

Stringifying Data to CSV

import { stringify } from "@std/csv/stringify";
import { assertEquals } from "@std/assert";

// Convert array of arrays to CSV
const arrayData = [["name", "age", "city"], ["john", "30", "new york"], ["mary", "25", "los angeles"]];
const csvString = stringify(arrayData);
assertEquals(csvString, "name,age,city\r\njohn,30,new york\r\nmary,25,los angeles\r\n");

// Convert array of objects to CSV
const objectData = [
  { name: "john", age: "30", city: "new york" },
  { name: "mary", age: "25", city: "los angeles" }
];

// When using an array of objects, you must specify columns to use
const customColumns = stringify(objectData, { columns: ["city", "name", "age"] });
assertEquals(customColumns, "city,name,age\r\nnew york,john,30\r\nlos angeles,mary,25\r\n");

Streaming Stringify Data to CSV

import { CsvStringifyStream } from "@std/csv/stringify-stream";
import { assertEquals } from "@std/assert";

async function writeCsvToTempFile(): Promise<string> {
  const path = await Deno.makeTempFile();
  using file = await Deno.open(path, { write: true });

  const readable = ReadableStream.from([
    { id: 1, name: "one" },
    { id: 2, name: "two" },
    { id: 3, name: "three" },
  ]);

  await readable
    .pipeThrough(new CsvStringifyStream({ columns: ["id", "name"] }))
    .pipeThrough(new TextEncoderStream())
    .pipeTo(file.writable);

  return path;
}

const path = await writeCsvToTempFile();
const content = await Deno.readTextFile(path);
assertEquals(content, "id,name\r\n1,one\r\n2,two\r\n3,three\r\n");

CSV Format Information

There are many kinds of CSV files; this module supports the format described in RFC 4180.

A csv file contains zero or more records of one or more fields per record. Each record is separated by the newline character. The final record may optionally be followed by a newline character.

field1,field2,field3

White space is considered part of a field.

Carriage returns before newline characters are silently removed.

Blank lines are ignored. A line with only whitespace characters (excluding the ending newline character) is not considered a blank line.

Fields which start and stop with the quote character " are called quoted-fields. The beginning and ending quote are not part of the field.

The source:

normal string,"quoted-field"

results in the fields

[`normal string`, `quoted-field`]

Within a quoted-field a quote character followed by a second quote character is considered a single quote.

"the ""word"" is true","a ""quoted-field"""

results in

[`the "word" is true`, `a "quoted-field"`]

Newlines and commas may be included in a quoted-field

"Multi-line
field","comma is ,"

results in

[`Multi-line
field`, `comma is ,`]

Add to your project Jump to heading

deno add jsr:@std/csv

See all symbols in @std/csv on

What is a CSV? Jump to heading

CSV (Comma-Separated Values) is a simple text format for storing tabular data, where each line represents a row and each value within the row is separated by a comma. It’s widely used for data exchange between applications, especially spreadsheets and databases.

When to use @std/csv Jump to heading

This package is great for reading and writing CSV files in your applications. It supports parsing CSV into arrays or objects, stringifying data back to CSV, and streaming for large files.

Tips Jump to heading

  • Use skipFirstRow: true to treat the first row as headers.
  • For objects, specify columns when stringifying.
  • Prefer streaming parsers for multi-GB datasets.

Did you find what you needed?

Privacy policy