0
# CAR Reading
1
2
Core functionality for reading CAR archives with full in-memory access to blocks and metadata. CarReader loads the entire archive into memory for random access, making it suitable for smaller CAR files or when frequent block lookups are needed.
3
4
## Capabilities
5
6
### CarReader Class
7
8
Provides blockstore-like access to a CAR archive with full random access capabilities.
9
10
```typescript { .api }
11
/**
12
* Provides blockstore-like access to a CAR archive
13
* Loads entire archive into memory for random access
14
*/
15
class CarReader {
16
/** CAR version number (1 or 2) */
17
readonly version: number;
18
19
/** Get the list of root CIDs defined in the CAR header */
20
getRoots(): Promise<CID[]>;
21
22
/** Check whether a given CID exists within the CAR */
23
has(key: CID): Promise<boolean>;
24
25
/** Fetch a Block from the CAR by CID, returns undefined if not found */
26
get(key: CID): Promise<Block | undefined>;
27
28
/** Returns async iterator over all Blocks in the CAR */
29
blocks(): AsyncGenerator<Block>;
30
31
/** Returns async iterator over all CIDs in the CAR */
32
cids(): AsyncGenerator<CID>;
33
34
/** Create CarReader from Uint8Array, decodes entire CAR into memory */
35
static fromBytes(bytes: Uint8Array): Promise<CarReader>;
36
37
/** Create CarReader from async iterable stream, decodes entire CAR into memory */
38
static fromIterable(asyncIterable: AsyncIterable<Uint8Array>): Promise<CarReader>;
39
}
40
```
41
42
**Usage Examples:**
43
44
```typescript
45
import { CarReader } from "@ipld/car/reader";
46
import fs from 'fs';
47
48
// From bytes
49
const carBytes = fs.readFileSync('archive.car');
50
const reader = await CarReader.fromBytes(carBytes);
51
52
// From stream
53
const stream = fs.createReadStream('archive.car');
54
const reader2 = await CarReader.fromIterable(stream);
55
56
// Access data
57
const roots = await reader.getRoots();
58
console.log(`CAR has ${roots.length} roots`);
59
60
// Check if CID exists
61
const exists = await reader.has(roots[0]);
62
if (exists) {
63
const block = await reader.get(roots[0]);
64
console.log(`Block size: ${block.bytes.length}`);
65
}
66
67
// Iterate through all blocks
68
for await (const block of reader.blocks()) {
69
console.log(`Block CID: ${block.cid}, Size: ${block.bytes.length}`);
70
}
71
72
// Iterate through CIDs only (more efficient if you don't need block data)
73
for await (const cid of reader.cids()) {
74
console.log(`CID: ${cid}`);
75
}
76
```
77
78
### Raw Block Reading (Node.js Only)
79
80
Direct file-based block reading using file descriptors for efficient access to indexed blocks.
81
82
```typescript { .api }
83
/**
84
* Read a block directly from a file descriptor (Node.js only)
85
* Used with CarIndexer to read blocks by their index information
86
* @param fd - File descriptor (number or FileHandle)
87
* @param blockIndex - Index information pointing to block location
88
* @returns Block data
89
*/
90
static readRaw(
91
fd: fs.promises.FileHandle | number,
92
blockIndex: BlockIndex
93
): Promise<Block>;
94
```
95
96
**Usage Example:**
97
98
```typescript
99
import fs from 'fs';
100
import { CarReader } from "@ipld/car/reader";
101
import { CarIndexer } from "@ipld/car/indexer";
102
103
// Open file and create indexer
104
const fd = await fs.promises.open('large-archive.car', 'r');
105
const stream = fs.createReadStream('large-archive.car');
106
const indexer = await CarIndexer.fromIterable(stream);
107
108
// Read specific blocks using raw access
109
for await (const blockIndex of indexer) {
110
const block = await CarReader.readRaw(fd, blockIndex);
111
console.log(`Block ${block.cid}: ${block.bytes.length} bytes`);
112
113
// Process only specific blocks
114
if (someCondition(block.cid)) {
115
processBlock(block);
116
}
117
}
118
119
await fd.close();
120
```
121
122
### Error Handling
123
124
Common errors when reading CAR files:
125
126
- **TypeError**: Thrown when invalid input types are provided
127
- **Error**: Thrown for malformed CAR data, invalid headers, or unexpected end of data
128
- **Unsupported CAR versions**: Only versions 1 and 2 are supported
129
130
```typescript
131
try {
132
const reader = await CarReader.fromBytes(invalidBytes);
133
} catch (error) {
134
if (error.message.includes('Invalid CAR')) {
135
console.log('Malformed CAR file');
136
} else if (error.message.includes('version')) {
137
console.log('Unsupported CAR version');
138
}
139
}
140
```
141
142
## Platform Differences
143
144
### Browser Environment
145
- Uses `CarReader` from `lib/reader-browser.js`
146
- Memory-based operations only
147
- No file descriptor support
148
149
### Node.js Environment
150
- Uses `CarReader` from `lib/reader.js` (extends browser version)
151
- Adds `readRaw()` static method for file descriptor access
152
- Supports both memory and file-based operations