> ## Documentation Index
> Fetch the complete documentation index at: https://numpyts.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# File I/O

> Save and load arrays in .npy, .npz, and text formats across Node.js and browsers.

numpy-ts supports the same file formats as NumPy: `.npy` (single array), `.npz` (multiple arrays), and delimited text files. The API is split across two entry points to keep browser bundles free of Node.js dependencies.

| Format          | Node.js (`numpy-ts/node`)             | Browser (`numpy-ts` or `numpy-ts/core`) |
| --------------- | ------------------------------------- | --------------------------------------- |
| `.npy`          | `save` / `load`                       | `serializeNpy` / `parseNpy`             |
| `.npz`          | `savez` / `savez_compressed` / `load` | `serializeNpz` / `parseNpz`             |
| Text (CSV, TSV) | `savetxt` / `loadtxt`                 | `serializeTxt` / `parseTxt`             |
| Text (flexible) | `genfromtxt` / `fromregex`            | `genfromtxt` / `fromregex`              |

<Note>
  Node.js functions read and write files on disk. Browser functions work with `ArrayBuffer`, `Uint8Array`, and strings -- you handle the network or file access yourself.
</Note>

## NPY files (single array)

The `.npy` format stores a single array with its dtype and shape metadata.

<Tabs>
  <Tab title="Node.js">
    ```typescript theme={null}
    import { array, save, load } from 'numpy-ts/node';

    const a = array([[1, 2, 3], [4, 5, 6]]);

    // Save to disk
    await save('matrix.npy', a);

    // Load from disk
    const loaded = await load('matrix.npy');
    console.log(loaded.shape); // [2, 3]
    ```

    Synchronous variants are also available:

    ```typescript theme={null}
    import { array, saveSync, loadSync } from 'numpy-ts/node';

    const a = array([1, 2, 3]);
    saveSync('data.npy', a);
    const loaded = loadSync('data.npy');
    ```
  </Tab>

  <Tab title="Browser">
    ```typescript theme={null}
    import { array, serializeNpy, parseNpy } from 'numpy-ts';

    const a = array([[1, 2, 3], [4, 5, 6]]);

    // Serialize to Uint8Array
    const bytes = serializeNpy(a);

    // Parse from ArrayBuffer (e.g., from fetch)
    const response = await fetch('https://example.com/matrix.npy');
    const buffer = await response.arrayBuffer();
    const loaded = parseNpy(buffer);
    console.log(loaded.shape); // [2, 3]
    ```

    You can also use the core entry point for smaller bundles:

    ```typescript theme={null}
    import { array, serializeNpy, parseNpy } from 'numpy-ts/core';
    ```
  </Tab>
</Tabs>

## NPZ archives (multiple arrays)

The `.npz` format stores multiple named arrays in a single ZIP archive. `savez_compressed` applies deflate compression.

<Tabs>
  <Tab title="Node.js">
    ```typescript theme={null}
    import { array, zeros, savez, savez_compressed, load } from 'numpy-ts/node';

    const weights = array([[0.1, 0.2], [0.3, 0.4]]);
    const biases = zeros([2]);

    // Save multiple arrays (uncompressed)
    await savez('model.npz', { weights, biases });

    // Save with compression
    await savez_compressed('model_compressed.npz', { weights, biases });

    // Load returns an object with a Map of arrays
    const result = await load('model.npz');
    const w = result.arrays.get('weights');
    const b = result.arrays.get('biases');
    ```
  </Tab>

  <Tab title="Browser">
    ```typescript theme={null}
    import { array, zeros, serializeNpz, parseNpz } from 'numpy-ts';

    const weights = array([[0.1, 0.2], [0.3, 0.4]]);
    const biases = zeros([2]);

    // Serialize to Uint8Array
    const bytes = await serializeNpz({ weights, biases });

    // Parse from ArrayBuffer (e.g., from fetch)
    const response = await fetch('https://example.com/model.npz');
    const buffer = await response.arrayBuffer();
    const result = await parseNpz(buffer);
    const w = result.arrays.get('weights');
    const b = result.arrays.get('biases');
    ```
  </Tab>
</Tabs>

## Text files

Load and save delimited text files such as CSV and TSV.

<Tabs>
  <Tab title="Node.js">
    ```typescript theme={null}
    import { array, loadtxt, savetxt } from 'numpy-ts/node';

    // Load a CSV file
    const data = await loadtxt('data.csv', { delimiter: ',' });

    // Load with options
    const filtered = await loadtxt('data.csv', {
      delimiter: ',',
      skiprows: 1,         // Skip header row
      usecols: [0, 2],     // Only columns 0 and 2
    });

    // Save as CSV
    const a = array([[1.1, 2.2], [3.3, 4.4]]);
    await savetxt('output.csv', a, {
      delimiter: ',',
      header: 'x,y',
      fmt: '%.2f',
    });
    ```
  </Tab>

  <Tab title="Browser">
    ```typescript theme={null}
    import { array, parseTxt, serializeTxt } from 'numpy-ts';

    // Parse from a string (e.g., from fetch or FileReader)
    const csv = `1.0,2.0,3.0
    4.0,5.0,6.0`;
    const data = parseTxt(csv, { delimiter: ',' });
    console.log(data.shape); // [2, 3]

    // Serialize to a string
    const a = array([[1.1, 2.2], [3.3, 4.4]]);
    const text = serializeTxt(a, {
      delimiter: ',',
      header: 'x,y',
      fmt: '%.2f',
    });
    console.log(text);
    // # x,y
    // 1.10,2.20
    // 3.30,4.40
    ```
  </Tab>
</Tabs>

## Flexible text loading

### genfromtxt

Like `loadtxt`, but handles missing values more gracefully.

<Tabs>
  <Tab title="Node.js">
    ```typescript theme={null}
    import { genfromtxt } from 'numpy-ts/node';

    const data = await genfromtxt('messy_data.csv', {
      delimiter: ',',
      missing_values: ['NA', '', '-'],
      filling_values: 0,
    });
    ```
  </Tab>

  <Tab title="Browser">
    ```typescript theme={null}
    import { genfromtxt } from 'numpy-ts';

    const csv = `1.0,2.0,3.0
    4.0,NA,6.0
    7.0,8.0,`;

    const data = genfromtxt(csv, {
      delimiter: ',',
      missing_values: ['NA', ''],
      filling_values: 0,
    });
    // [[1, 2, 3], [4, 0, 6], [7, 8, 0]]
    ```
  </Tab>
</Tabs>

### fromregex

Extract numeric data from unstructured text using regular expressions.

<Tabs>
  <Tab title="Node.js">
    ```typescript theme={null}
    import { fromregex } from 'numpy-ts/node';

    // File contents: "Point: x=1.5, y=2.3\nPoint: x=4.0, y=5.1"
    const points = await fromregex('points.txt', /x=([\d.]+), y=([\d.]+)/);
    console.log(points.shape); // [2, 2]
    console.log(points.toArray()); // [[1.5, 2.3], [4.0, 5.1]]
    ```
  </Tab>

  <Tab title="Browser">
    ```typescript theme={null}
    import { fromregex } from 'numpy-ts';

    const text = `Point: x=1.5, y=2.3
    Point: x=4.0, y=5.1`;

    const points = fromregex(text, /x=([\d.]+), y=([\d.]+)/);
    console.log(points.toArray()); // [[1.5, 2.3], [4.0, 5.1]]
    ```
  </Tab>
</Tabs>

## Why a separate Node.js entry point?

<Note>
  File I/O functions that read and write to the filesystem are in `numpy-ts/node` because they depend on Node.js built-in modules (`fs`, `fs/promises`). Keeping them in a separate entry point means that `numpy-ts` and `numpy-ts/core` never import `fs`, so they work cleanly in browsers and edge runtimes without bundler polyfills.

  If you only need serialization and parsing (not disk access), use `serializeNpy`, `parseNpy`, `serializeNpz`, `parseNpz`, `serializeTxt`, and `parseTxt` from the main entry points.
</Note>

## NumPy compatibility

Files saved by numpy-ts can be loaded by Python NumPy, and vice versa:

```python theme={null}
# Python
import numpy as np

# Load a file saved by numpy-ts
arr = np.load('matrix.npy')

# Save a file for numpy-ts to load
np.save('from_python.npy', np.array([[1, 2], [3, 4]]))
```

```typescript theme={null}
// TypeScript
import { load } from 'numpy-ts/node';

const arr = await load('from_python.npy');
console.log(arr.toArray()); // [[1, 2], [3, 4]]
```

<Warning>
  numpy-ts does not support NumPy object arrays, structured arrays, or pickle-based `.npy` files. Only numeric dtypes (`float64`, `float32`, `int32`, `int16`, `int8`, `uint32`, `uint16`, `uint8`, `bool`, `complex128`, `complex64`) are supported.
</Warning>
