Node.js File System
The fs (file system) module lets Node.js read and change files and folders on the computer.
Three Styles of fs
| Style | Import | Example |
|---|---|---|
| Promises (recommended) | node:fs/promises | await readFile(...) |
| Callbacks | node:fs | readFile(..., (err, data) => {}) |
| Synchronous | node:fs | readFileSync(...) |
The examples here use promises with async/await in an ES module ("type": "module" in package.json). Synchronous functions block the whole program, so use them only in small scripts, never inside a busy server.
Reading a File
Create menu.txt next to your script:
Example
Chai - Rs 80
Paratha - Rs 120
Omelette - Rs 200Example
import { readFile } from "node:fs/promises";
const text = await readFile("menu.txt", "utf8");
console.log(text);Chai - Rs 80 Paratha - Rs 120 Omelette - Rs 200
The "utf8" argument gives you text. Without it, you get a Buffer (raw bytes).
Writing a File
writeFile creates the file if it does not exist and replaces it if it does:
Example
import { writeFile } from "node:fs/promises";
await writeFile("receipt.txt", "Customer: Bilal\nTotal: Rs 400\n");
console.log("Receipt saved");Receipt saved
Adding to a File
appendFile adds text to the end without deleting what is already there. It is useful for logs:
Example
import { appendFile } from "node:fs/promises";
const time = new Date().toISOString();
await appendFile("visits.log", `${time} - New visitor\n`);Other Common Operations
Example
import { rename, unlink, mkdir, readdir, stat } from "node:fs/promises";
await mkdir("reports/2026", { recursive: true }); // create folders
await rename("receipt.txt", "reports/2026/receipt-1.txt"); // move or rename
const files = await readdir("reports/2026"); // list a folder
console.log(files);
const info = await stat("reports/2026/receipt-1.txt");
console.log("Size in bytes:", info.size);
await unlink("visits.log"); // delete a file[ 'receipt-1.txt' ] Size in bytes: 30
| Function | Job |
|---|---|
readFile | Read a whole file |
writeFile | Create or replace a file |
appendFile | Add to the end of a file |
rename | Rename or move a file |
unlink | Delete a file |
mkdir | Create a folder |
readdir | List what is inside a folder |
rm | Delete a file or folder (use { recursive: true } for folders) |
stat | Get size and dates of a file |
Handling Errors
If a file does not exist, readFile throws an error with the code ENOENT. Catch it:
Example
import { readFile } from "node:fs/promises";
try {
const data = await readFile("missing.txt", "utf8");
console.log(data);
} catch (err) {
if (err.code === "ENOENT") {
console.log("File not found. Creating a new one is a good idea.");
} else {
throw err;
}
}File not found. Creating a new one is a good idea.
Working with JSON Files
JSON files are a simple way to store data in small projects:
Example
import { readFile, writeFile } from "node:fs/promises";
const students = JSON.parse(await readFile("students.json", "utf8"));
students.push({ name: "Ayesha", course: "Web Development" });
await writeFile("students.json", JSON.stringify(students, null, 2));
console.log("Total students:", students.length);JSON.stringify(data, null, 2) saves the file with neat indentation.
Paths Relative to Your File
A path like "menu.txt" is relative to the folder where you ran the command, not where the script is. To always point next to the script, build the path from import.meta.dirname:
Example
import path from "node:path";
import { readFile } from "node:fs/promises";
const file = path.join(import.meta.dirname, "menu.txt");
const text = await readFile(file, "utf8");In CommonJS files, use __dirname instead.
For large files, such as a 2 GB video or a big CSV, use streams (fs.createReadStream) so Node.js reads the file piece by piece instead of loading it all into memory.
Exercise
Exercise
Which function adds text to the end of a file without removing its old content?
