---
url: /process-functions/csv-reader.md
description: >-
  Reads a CSV file row by row, as objects keyed by column heading or as raw
  value arrays.
---

# &#x20;CSVReader

Reads a CSV file row by row, as objects keyed by column heading or as raw value arrays.

::: code-group

```js [load.js]
const reader = datasource.csvRead("uploads/actuals.csv", 0);

for (const row of reader) {
    cube.set(Number(row.amount), "Sales", row.year, row.month, row.product, "Actual");
}
```

```csv [actuals.csv]
year,month,product,amount
2026,Jan,Widgets,1200.50
2026,Jan,Gadgets,830
```

:::

## Constructor

### datasource.csvRead `datasource.csvRead(fileName, skipLines, ignoreEscapeCharacter, delimiter)`  {#datasource-csvread}

Opens a CSV file from the filesystem and returns a `CSVReader`, or `null` when the file can't be opened.

| Parameter | Type | Description |
|---|---|---|
| `fileName` | `string` | The path of the file, for example `"uploads/actuals.csv"`. |
| `skipLines` | `number` | The number of lines to skip before the heading row. Use `0` when the file starts with its headings. |
| `ignoreEscapeCharacter` | `boolean` | Optional. `true` to treat backslashes as ordinary characters. |
| `delimiter` | `string` | Optional. The field delimiter. Detected from the file when omitted. |

```js
// A file that starts with its headings
const reader = datasource.csvRead("uploads/actuals.csv", 0);

// A file with two title lines above the headings
const reader = datasource.csvRead("uploads/trial_balance.csv", 2);

// A pipe-delimited file
const reader = datasource.csvRead("uploads/extract.txt", 0, false, "|");
```

## Overview

* **Headings:** when the first row looks like a heading, its values become the property names on each row. Otherwise columns are named `column0`, `column1` and so on.
* **Format:** the delimiter, quote character and encoding are detected from the file. Override them with the setter methods **before the first read**.
* **Values are strings:** convert with `Number(...)` before writing to a cube or doing arithmetic.
* **Looping:** `for...of` is the simplest way to read every row. Use a `while (!reader.isEOF())` loop for one row at a time, or when you want arrays from `readValues()`.

::: code-group

```js [for...of]
// Each row is an object keyed by column heading
for (const row of reader) {
    console.log(row.product + ": " + row.amount);
}
```

```js [while + read()]
// Same row objects, one call at a time
while (!reader.isEOF()) {
    const row = reader.read();
    console.log(row.product + ": " + row.amount);
}
```

```js [while + readValues()]
// Each row is an array of strings, in column order
while (!reader.isEOF()) {
    const values = reader.readValues();
    console.log(values[2] + ": " + values[3]);
}
```

:::

## Methods

### read `read()`  {#read}

Returns the next row as an object keyed by column heading, or `null` at the end of the file. Each `for...of` iteration yields the same object.

### readValues `readValues()`  {#readvalues}

Returns the next row as an array of strings in column order, or `null` at the end of the file. Use it for files without headings, or to pick columns by position.

### isEOF `isEOF()`  {#iseof}

Returns `true` once the reader has passed the last row of the file.

### close `close()`  {#close}

Closes the file. Readers close automatically when the process finishes, so only call this to release the file early, such as before renaming or deleting it.

```js
reader.close();
datasource.renameFile("uploads/actuals.csv", "archive/actuals.csv");
```

### setDelimiter `setDelimiter(delimiter)` {#setdelimiter}

Sets the field delimiter, overriding auto-detection. Call it before the first read.

| Parameter | Type | Description |
|---|---|---|
| `delimiter` | `string` | The delimiter, for example `";"` or `"\|"`. Pass `"\t"` or `"t"` for tab. |

### getDelimiter `getDelimiter()`  {#getdelimiter}

Returns the delimiter set on the reader, or `null` when it will be auto-detected.

### setQuoteCharacter `setQuoteCharacter(quoteCharacter)` {#setquotecharacter}

Sets the quote character, overriding auto-detection. Call it before the first read.

| Parameter | Type | Description |
|---|---|---|
| `quoteCharacter` | `string` | The quote character, for example `"'"`. |

### getQuoteCharacter `getQuoteCharacter()`  {#getquotecharacter}

Returns the quote character set on the reader, or `null` when it will be auto-detected.

### setCharset `setCharset(charset)` {#setcharset}

Sets the character encoding, overriding auto-detection. Call it before the first read. Unknown encoding names are ignored.

| Parameter | Type | Description |
|---|---|---|
| `charset` | `string` | The encoding name, for example `"UTF-8"` or `"windows-1252"`. |

### getCharset `getCharset()`  {#getcharset}

Returns the character encoding used to read the file, either detected or set with `setCharset()`.

### setTrimValues `setTrimValues(trim)` {#settrimvalues}

Turns on trimming of spaces around each value. Call it before the first read.

| Parameter | Type | Description |
|---|---|---|
| `trim` | `boolean` | `true` to trim spaces around each value. |

### getTrimValues `getTrimValues()`  {#gettrimvalues}

Returns whether spaces around each value are trimmed.

## Examples

### A file with a title block and semicolons

Skip the title lines with `skipLines`, then set the format before reading.

::: code-group

```js [load-trial-balance.js]
const reader = datasource.csvRead("uploads/trial_balance.txt", 2);
reader.setDelimiter(";");
reader.setTrimValues(true);

for (const row of reader) {
    cube.set(Number(row.debit) - Number(row.credit), "GL", row.account, "Jan", "2026", "Actual");
}
```

```csv [trial_balance.txt]
Trial Balance Export
Generated 2026-02-01
account;debit;credit
4000;0.00;15230.50
5000;8120.00;0.00
```

:::

### A file without headings

::: code-group

```js [load-rates.js]
const reader = datasource.csvRead("uploads/rates.csv", 0);

while (!reader.isEOF()) {
    const [currency, year, month, rate] = reader.readValues();
    cube.set(Number(rate), "FX Rates", year, month, currency);
}
```

```csv [rates.csv]
AUD,2026,Jan,0.65
NZD,2026,Jan,0.60
```

:::

### Add up rows that land on the same cell

```js
const reader = datasource.csvRead("uploads/invoices.csv", 0);

for (const row of reader) {
    cube.increment(Number(row.total), "Revenue", row.customer, row.month, "Actual");
}
```

## Related

* [CSVWriter](/process-functions/csv-writer): writes CSV files.
