Node.js File System
Node.js File System
Section titled “Node.js File System”The fs module provides file system access. Always prefer the async (promise-based) API in servers to avoid blocking the event loop.
Reading Files
Section titled “Reading Files”import { readFile, readFileSync } from 'fs/promises'; // modern async
// Async (recommended)const content = await readFile('./data.txt', 'utf-8');
// Sync (only use in startup code — blocks the event loop)const content = readFileSync('./data.txt', 'utf-8');Read JSON:
const raw = await readFile('./config.json', 'utf-8');const config = JSON.parse(raw);
// Or with require() in CommonJSconst config = require('./config.json');Writing Files
Section titled “Writing Files”import { writeFile, appendFile } from 'fs/promises';
// Write (creates or overwrites)await writeFile('./output.txt', 'Hello, world!', 'utf-8');
// Appendawait appendFile('./log.txt', `${new Date().toISOString()} - Event\n`);
// Write JSONawait writeFile('./data.json', JSON.stringify(data, null, 2), 'utf-8');Checking if a File Exists
Section titled “Checking if a File Exists”import { access, constants } from 'fs/promises';
async function fileExists(path: string): Promise<boolean> { try { await access(path, constants.F_OK); return true; } catch { return false; }}File Metadata
Section titled “File Metadata”import { stat } from 'fs/promises';
const info = await stat('./myfile.txt');console.log(info.size); // bytesconsole.log(info.isFile()); // trueconsole.log(info.isDirectory()); // falseconsole.log(info.mtime); // last modified dateDirectory Operations
Section titled “Directory Operations”import { mkdir, readdir, rm } from 'fs/promises';
// Create directory (recursive creates parent dirs too)await mkdir('./logs/2025', { recursive: true });
// List directory contentsconst files = await readdir('./src');const withStats = await readdir('./src', { withFileTypes: true });withStats.filter(e => e.isFile()).map(e => e.name);
// Delete directory recursivelyawait rm('./temp', { recursive: true, force: true });Copying and Moving Files
Section titled “Copying and Moving Files”import { copyFile, rename } from 'fs/promises';
// Copyawait copyFile('./source.txt', './destination.txt');
// Move / renameawait rename('./old-name.txt', './new-name.txt');Working with Paths
Section titled “Working with Paths”Always use the path module — never concatenate paths with strings:
import path from 'path';
// Join path segments (handles OS separators)const filePath = path.join(__dirname, 'data', 'users.json');
// Resolve to absolute pathconst absPath = path.resolve('./relative/path');
// Get partspath.basename('/usr/local/bin/node'); // 'node'path.dirname('/usr/local/bin/node'); // '/usr/local/bin'path.extname('config.json'); // '.json'
// __dirname equivalent in ESMimport { fileURLToPath } from 'url';const __dirname = path.dirname(fileURLToPath(import.meta.url));Watching for Changes
Section titled “Watching for Changes”import { watch } from 'fs';
const watcher = watch('./src', { recursive: true }, (event, filename) => { console.log(`${event}: ${filename}`);});
// Stop watchingwatcher.close();Reading Files Line by Line
Section titled “Reading Files Line by Line”import { createReadStream } from 'fs';import { createInterface } from 'readline';
async function processLines(filePath: string) { const stream = createReadStream(filePath); const rl = createInterface({ input: stream, crlfDelay: Infinity });
for await (const line of rl) { // process each line without loading entire file into memory console.log(line); }}Error Handling
Section titled “Error Handling”import { readFile } from 'fs/promises';
try { const content = await readFile('./missing.txt', 'utf-8');} catch (err) { if ((err as NodeJS.ErrnoException).code === 'ENOENT') { console.log('File not found'); } else { throw err; }}Common Error Codes
Section titled “Common Error Codes”| Code | Meaning |
|---|---|
ENOENT | No such file or directory |
EACCES | Permission denied |
EEXIST | File already exists |
EISDIR | Is a directory (expected a file) |
ENOTDIR | Not a directory (expected a directory) |