The fs Module: Reading & Writing Files
13 min read
The fs Module
The fs (file system) module lets you interact with the file system: read files, write files, delete them, create directories, and watch for changes. Every operation has both a synchronous (blocking) version and an asynchronous (non-blocking) version.
Synchronous vs Asynchronous
Sync methods (ending in Sync) block the event loop until they finish. They are convenient in scripts and startup code, but you should avoid them in servers where blocking the event loop harms all concurrent requests.
js
const fs = require("fs");
const path = require("path");
const filePath = path.join(__dirname, "data.txt");
// --- Synchronous ---
fs.writeFileSync(filePath, "Hello, file system!", "utf8");
const content = fs.readFileSync(filePath, "utf8");
console.log(content); // Hello, file system!Callback-based (Asynchronous)
js
fs.readFile(filePath, "utf8", function(err, data) {
if (err) {
console.error("Error reading file:", err.message);
return;
}
console.log(data);
});Promise-based with fs/promises
Node.js provides fs/promises (or fs.promises) which returns Promises instead of using callbacks. Combine with async/await for clean, readable async file I/O.
js
const fs = require("fs/promises");
const path = require("path");
async function processFile() {
const filePath = path.join(__dirname, "notes.txt");
await fs.writeFile(filePath, "Line 1\nLine 2\nLine 3", "utf8");
const content = await fs.readFile(filePath, "utf8");
const lines = content.split("\n");
console.log("Total lines:", lines.length);
// Append more content
await fs.appendFile(filePath, "\nLine 4", "utf8");
// Check if a file exists
try {
await fs.access(filePath);
console.log("File exists!");
} catch {
console.log("File not found");
}
// Delete the file
await fs.unlink(filePath);
}
processFile().catch(console.error);Prefer fs/promises with async/await in all new code. It is the most readable and avoids callback nesting ("callback hell").
Ready to test yourself?
Practice Node.js— quiz & coding exercises