0
# File Descriptors
1
2
Low-level file descriptor operations for fine-grained control over file access, positioning, and data manipulation. File descriptors provide precise control over file operations with manual buffer management.
3
4
## Capabilities
5
6
### File Opening
7
8
Open files and obtain file descriptors for low-level operations.
9
10
```javascript { .api }
11
/**
12
* Synchronously open a file and return a file descriptor
13
* @param path - File path to open
14
* @param flags - File open flags (string or number)
15
* @param mode - File mode for newly created files
16
* @returns File descriptor number
17
*/
18
openSync(path: string | Buffer, flags: string | number, mode?: number): number;
19
20
/**
21
* Asynchronously open a file and return a file descriptor
22
* @param path - File path to open
23
* @param flags - File open flags (string or number)
24
* @param mode - File mode for newly created files
25
* @param callback - Completion callback with file descriptor
26
*/
27
open(path: string | Buffer, flags: string | number, mode?: number, callback?: (err?: Error, fd?: number) => void): void;
28
open(path: string | Buffer, flags: string | number, callback: (err?: Error, fd?: number) => void): void;
29
```
30
31
**File Flags:**
32
- `'r'` - Open for reading (file must exist)
33
- `'r+'` - Open for reading and writing (file must exist)
34
- `'w'` - Open for writing (truncates file or creates new)
35
- `'wx'` - Open for writing exclusively (fails if file exists)
36
- `'w+'` - Open for reading and writing (truncates or creates)
37
- `'wx+'` - Open for reading and writing exclusively
38
39
**Usage Examples:**
40
41
```javascript
42
// Open file for reading
43
const fd = fs.openSync('/data.txt', 'r');
44
45
// Open for writing with specific mode
46
const writeFd = fs.openSync('/output.txt', 'w', 0o644);
47
48
// Open exclusively (fail if exists)
49
try {
50
const exclusiveFd = fs.openSync('/unique.txt', 'wx');
51
console.log('File opened exclusively');
52
} catch (err) {
53
console.log('File already exists');
54
}
55
56
// Async file opening
57
fs.open('/async.txt', 'r+', (err, fd) => {
58
if (!err) {
59
console.log('File opened with fd:', fd);
60
// Remember to close the file descriptor
61
fs.close(fd, () => {});
62
}
63
});
64
65
// Promise-based opening
66
const fd = await fs.promises.open('/promise.txt', 'w');
67
```
68
69
### File Closing
70
71
Close file descriptors to free system resources.
72
73
```javascript { .api }
74
/**
75
* Synchronously close a file descriptor
76
* @param fd - File descriptor to close
77
*/
78
closeSync(fd: number): void;
79
80
/**
81
* Asynchronously close a file descriptor
82
* @param fd - File descriptor to close
83
* @param callback - Completion callback
84
*/
85
close(fd: number, callback: (err?: Error) => void): void;
86
```
87
88
**Usage Examples:**
89
90
```javascript
91
// Open, use, and close file
92
const fd = fs.openSync('/temp.txt', 'w');
93
try {
94
// ... use file descriptor
95
fs.writeSync(fd, 'Hello World');
96
} finally {
97
fs.closeSync(fd); // Always close
98
}
99
100
// Async close
101
fs.open('/file.txt', 'r', (err, fd) => {
102
if (!err) {
103
// ... use fd
104
fs.close(fd, (closeErr) => {
105
if (!closeErr) {
106
console.log('File closed successfully');
107
}
108
});
109
}
110
});
111
```
112
113
### Reading with File Descriptors
114
115
Read data from files using file descriptors with precise buffer control.
116
117
```javascript { .api }
118
/**
119
* Synchronously read data from a file descriptor into a buffer
120
* @param fd - File descriptor to read from
121
* @param buffer - Buffer to write data into
122
* @param offset - Offset in buffer to start writing
123
* @param length - Number of bytes to read
124
* @param position - Position in file to read from (null for current position)
125
* @returns Number of bytes read
126
*/
127
readSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number | null): number;
128
129
/**
130
* Asynchronously read data from a file descriptor into a buffer
131
* @param fd - File descriptor to read from
132
* @param buffer - Buffer to write data into
133
* @param offset - Offset in buffer to start writing
134
* @param length - Number of bytes to read
135
* @param position - Position in file to read from (null for current position)
136
* @param callback - Completion callback with bytes read
137
*/
138
read(fd: number, buffer: Buffer, offset: number, length: number, position?: number | null, callback?: (err?: Error, bytesRead?: number) => void): void;
139
```
140
141
**Usage Examples:**
142
143
```javascript
144
// Read file content into buffer
145
const fd = fs.openSync('/data.txt', 'r');
146
const buffer = Buffer.alloc(1024);
147
148
try {
149
const bytesRead = fs.readSync(fd, buffer, 0, buffer.length, 0);
150
const content = buffer.subarray(0, bytesRead).toString('utf8');
151
console.log('Read content:', content);
152
} finally {
153
fs.closeSync(fd);
154
}
155
156
// Read from specific position
157
const fd2 = fs.openSync('/large-file.txt', 'r');
158
const chunk = Buffer.alloc(100);
159
const bytesRead = fs.readSync(fd2, chunk, 0, 100, 500); // Read 100 bytes from position 500
160
fs.closeSync(fd2);
161
162
// Async reading
163
fs.open('/async-read.txt', 'r', (err, fd) => {
164
if (err) return;
165
166
const buffer = Buffer.alloc(256);
167
fs.read(fd, buffer, 0, buffer.length, null, (readErr, bytesRead) => {
168
if (!readErr) {
169
const data = buffer.subarray(0, bytesRead);
170
console.log('Read data:', data.toString());
171
}
172
fs.close(fd, () => {});
173
});
174
});
175
```
176
177
### Writing with File Descriptors
178
179
Write data to files using file descriptors with precise positioning control.
180
181
```javascript { .api }
182
/**
183
* Synchronously write data from a buffer or string to a file descriptor
184
* @param fd - File descriptor to write to
185
* @param buffer - Buffer or string containing data to write
186
* @param offset - Offset in buffer to start reading from (for Buffer)
187
* @param length - Number of bytes to write (for Buffer)
188
* @param position - Position in file to write to (null for current position)
189
* @returns Number of bytes written
190
*/
191
writeSync(fd: number, buffer: Buffer, offset?: number, length?: number, position?: number | null): number;
192
writeSync(fd: number, string: string, position?: number | null, encoding?: string): number;
193
194
/**
195
* Asynchronously write data from a buffer or string to a file descriptor
196
* @param fd - File descriptor to write to
197
* @param buffer - Buffer or string containing data to write
198
* @param offset - Offset in buffer to start reading from
199
* @param length - Number of bytes to write
200
* @param position - Position in file to write to (null for current position)
201
* @param callback - Completion callback with bytes written
202
*/
203
write(fd: number, buffer: Buffer, offset?: number, length?: number, position?: number | null, callback?: (err?: Error, bytesWritten?: number) => void): void;
204
write(fd: number, string: string, position?: number | null, encoding?: string, callback?: (err?: Error, bytesWritten?: number) => void): void;
205
```
206
207
**Usage Examples:**
208
209
```javascript
210
// Write string to file
211
const fd = fs.openSync('/output.txt', 'w');
212
try {
213
const bytesWritten = fs.writeSync(fd, 'Hello, World!');
214
console.log(`Wrote ${bytesWritten} bytes`);
215
} finally {
216
fs.closeSync(fd);
217
}
218
219
// Write buffer to specific position
220
const fd2 = fs.openSync('/patchable.txt', 'r+');
221
const data = Buffer.from('patched');
222
fs.writeSync(fd2, data, 0, data.length, 10); // Write at position 10
223
fs.closeSync(fd2);
224
225
// Write with encoding
226
const fd3 = fs.openSync('/unicode.txt', 'w');
227
fs.writeSync(fd3, 'Hello 世界', 0, 'utf8');
228
fs.closeSync(fd3);
229
230
// Async writing
231
fs.open('/async-write.txt', 'w', (err, fd) => {
232
if (err) return;
233
234
const buffer = Buffer.from('Async data');
235
fs.write(fd, buffer, 0, buffer.length, null, (writeErr, bytesWritten) => {
236
if (!writeErr) {
237
console.log(`Wrote ${bytesWritten} bytes`);
238
}
239
fs.close(fd, () => {});
240
});
241
});
242
```
243
244
### File Descriptor Statistics
245
246
Get file information using file descriptors.
247
248
```javascript { .api }
249
/**
250
* Synchronously get file statistics using a file descriptor
251
* @param fd - File descriptor
252
* @returns Stats object with file information
253
*/
254
fstatSync(fd: number): Stats;
255
256
/**
257
* Asynchronously get file statistics using a file descriptor
258
* @param fd - File descriptor
259
* @param callback - Completion callback with stats
260
*/
261
fstat(fd: number, callback: (err?: Error, stats?: Stats) => void): void;
262
263
interface Stats {
264
isFile(): boolean;
265
isDirectory(): boolean;
266
isSymbolicLink(): boolean;
267
size: number;
268
mode: number;
269
uid: number;
270
gid: number;
271
atime: Date;
272
mtime: Date;
273
ctime: Date;
274
birthtime: Date;
275
// ... other properties
276
}
277
```
278
279
**Usage Examples:**
280
281
```javascript
282
// Get file stats using file descriptor
283
const fd = fs.openSync('/file.txt', 'r');
284
try {
285
const stats = fs.fstatSync(fd);
286
console.log(`File size: ${stats.size} bytes`);
287
console.log(`Is file: ${stats.isFile()}`);
288
console.log(`Modified: ${stats.mtime}`);
289
} finally {
290
fs.closeSync(fd);
291
}
292
293
// Async stats
294
fs.open('/data.txt', 'r', (err, fd) => {
295
if (err) return;
296
297
fs.fstat(fd, (statErr, stats) => {
298
if (!statErr) {
299
console.log('File info:', {
300
size: stats.size,
301
isFile: stats.isFile(),
302
modified: stats.mtime
303
});
304
}
305
fs.close(fd, () => {});
306
});
307
});
308
```
309
310
### File Descriptor Permissions
311
312
Change file permissions using file descriptors.
313
314
```javascript { .api }
315
/**
316
* Synchronously change file permissions using a file descriptor
317
* @param fd - File descriptor
318
* @param mode - New file mode (permissions)
319
*/
320
fchmodSync(fd: number, mode: number | string): void;
321
322
/**
323
* Asynchronously change file permissions using a file descriptor
324
* @param fd - File descriptor
325
* @param mode - New file mode (permissions)
326
* @param callback - Completion callback
327
*/
328
fchmod(fd: number, mode: number | string, callback?: (err?: Error) => void): void;
329
```
330
331
**Usage Examples:**
332
333
```javascript
334
// Change file permissions via file descriptor
335
const fd = fs.openSync('/secure.txt', 'r+');
336
try {
337
fs.fchmodSync(fd, 0o600); // Owner read/write only
338
console.log('Permissions changed');
339
} finally {
340
fs.closeSync(fd);
341
}
342
343
// Async permission change
344
fs.open('/data.txt', 'r+', (err, fd) => {
345
if (err) return;
346
347
fs.fchmod(fd, '644', (chmodErr) => {
348
if (!chmodErr) {
349
console.log('Permissions updated');
350
}
351
fs.close(fd, () => {});
352
});
353
});
354
```
355
356
### File Synchronization
357
358
Force file data to be written to storage.
359
360
```javascript { .api }
361
/**
362
* Synchronously force file data and metadata to be written to storage
363
* @param fd - File descriptor
364
*/
365
fsyncSync(fd: number): void;
366
367
/**
368
* Synchronously force file data (not metadata) to be written to storage
369
* @param fd - File descriptor
370
*/
371
fdatasyncSync(fd: number): void;
372
373
/**
374
* Asynchronously force file data and metadata to be written to storage
375
* @param fd - File descriptor
376
* @param callback - Completion callback
377
*/
378
fsync(fd: number, callback?: (err?: Error) => void): void;
379
380
/**
381
* Asynchronously force file data (not metadata) to be written to storage
382
* @param fd - File descriptor
383
* @param callback - Completion callback
384
*/
385
fdatasync(fd: number, callback?: (err?: Error) => void): void;
386
```
387
388
**Usage Examples:**
389
390
```javascript
391
// Ensure data is written to disk
392
const fd = fs.openSync('/critical.txt', 'w');
393
try {
394
fs.writeSync(fd, 'Important data');
395
fs.fsyncSync(fd); // Force write to disk
396
console.log('Data synchronized to storage');
397
} finally {
398
fs.closeSync(fd);
399
}
400
401
// Data-only sync (faster than fsync)
402
fs.fdatasyncSync(fd); // Sync data but not metadata
403
404
// Async sync
405
fs.open('/log.txt', 'w', (err, fd) => {
406
if (err) return;
407
408
fs.write(fd, 'Log entry', (writeErr) => {
409
if (writeErr) return;
410
411
fs.fsync(fd, (syncErr) => {
412
if (!syncErr) {
413
console.log('Log entry synchronized');
414
}
415
fs.close(fd, () => {});
416
});
417
});
418
});
419
```
420
421
## Best Practices
422
423
```javascript
424
// Always close file descriptors
425
function safeFileOperation(path) {
426
const fd = fs.openSync(path, 'r');
427
try {
428
// Perform operations
429
const buffer = Buffer.alloc(1024);
430
const bytesRead = fs.readSync(fd, buffer, 0, buffer.length, 0);
431
return buffer.subarray(0, bytesRead);
432
} finally {
433
fs.closeSync(fd); // Always close
434
}
435
}
436
437
// Use try-finally for exception safety
438
function writeToFile(path, data) {
439
const fd = fs.openSync(path, 'w');
440
try {
441
fs.writeSync(fd, data);
442
fs.fsyncSync(fd); // Ensure data is written
443
} finally {
444
fs.closeSync(fd);
445
}
446
}
447
448
// Handle async operations properly
449
function asyncFileRead(path, callback) {
450
fs.open(path, 'r', (err, fd) => {
451
if (err) return callback(err);
452
453
const buffer = Buffer.alloc(1024);
454
fs.read(fd, buffer, 0, buffer.length, 0, (readErr, bytesRead) => {
455
// Always close fd, even on error
456
fs.close(fd, (closeErr) => {
457
if (readErr) return callback(readErr);
458
if (closeErr) return callback(closeErr);
459
460
callback(null, buffer.subarray(0, bytesRead));
461
});
462
});
463
});
464
}
465
```
466
467
## Error Handling
468
469
Common file descriptor errors:
470
471
- `EBADF` - Bad file descriptor (already closed or invalid)
472
- `EMFILE` - Too many open files
473
- `ENOENT` - File doesn't exist (openSync with 'r' flag)
474
- `EEXIST` - File exists (openSync with 'wx' flag)
475
- `EISDIR` - Is a directory (cannot open directory as file)
476
- `EPERM` - Permission denied