Chapter 1.5☕ 16 min read

File System fs Module — Biryani Menu File Read Karna

The fs module lets you interact with the file system — read, write, update, delete, and watch files.

01What is fs Module? — Kitchen Storage

The fs (file system) module is a built-in Node.js module that lets you work with files and directories on your computer. It comes with Node.js — no installation needed.

Think of it as your chai tapri kitchen storage:

  • Reading files = Menu card padhna (biryani types, prices check karna)
  • Writing files = Naya menu likhna (prices update karna)
  • Creating directories = Naya storage rack rakhna (chai patti, sugar ke liye)
  • Watching files = Chef ko dekhna jab bhi menu badalta hai
  • Deleting files= Purana menu hatana (seasonal items hatao)

The fs module has three APIs for almost every operation:

API StyleExampleBest For
Callback (async)fs.readFile(path, callback)Simple async code
Sync (blocking)fs.readFileSync(path)Startup scripts, one-time operations
Promise (modern async)fs.promises.readFile(path)Modern async/await code (RECOMMENDED)

Always prefer the Promise version (fs.promises) for production code. It's non-blocking and works beautifully with async/await.

02Reading Files — Biryani Menu Padhna

Reading a file is like reading your chai tapri menu. Let's say you have a file called menu.txt:

--- Chai Tapri Menu ---
Ginger Chai - Rs. 10
Elaichi Chai - Rs. 12
Special Chai - Rs. 15
Biscuit (Parle-G) - Rs. 5
Samosa - Rs. 15

1. Callback version (old style):

const fs = require('fs');

fs.readFile('menu.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('Error reading menu:', err.message);
    return;
  }
  console.log('Menu loaded!');
  console.log(data);
});

console.log('Reading menu...'); // This runs FIRST (non-blocking!)

2. Synchronous version (blocking — use sparingly):

const fs = require('fs');

try {
  const data = fs.readFileSync('menu.txt', 'utf8');
  console.log('Menu loaded!');
  console.log(data);
} catch (err) {
  console.error('Error:', err.message);
}
// ⛔ This BLOCKS the event loop until file is read!

3. Promise version (RECOMMENDED — modern):

const fs = require('fs/promises');  // Note: fs/promises

async function loadMenu() {
  try {
    const data = await fs.readFile('menu.txt', 'utf8');
    console.log('Menu loaded!');
    console.log(data);
  } catch (err) {
    console.error('Error:', err.message);
  }
}

loadMenu();
console.log('This runs first — non-blocking!');

Key options for readFile:

  • 'utf8' — Returns file content as a string (without it, you get a Buffer)
  • No encoding — Returns a raw Buffer (binary data, images, files)

Buffer vs String: Without 'utf8', readFile returns a Buffer object. For text files, always pass 'utf8'. For images or binary files, use Buffer.

03Writing Files — Naya Order Likho

Writing files is like updating your chai menu when prices change or adding new orders.

1. Writing a new file (overwrites if exists):

const fs = require('fs/promises');

async function writeMenu() {
  const newMenu = `--- Chai Tapri Menu (UPDATED) ---
Ginger Chai - Rs. 12  (price increased!)
Elaichi Chai - Rs. 15
Special Chai - Rs. 20
Biscuit (Parle-G) - Rs. 5
Samosa - Rs. 15
Cold Coffee (NEW!) - Rs. 25`;

  await fs.writeFile('menu.txt', newMenu, 'utf8');
  console.log('Menu updated successfully!');
}

writeMenu();

2. Appending to a file (add without overwriting):

await fs.appendFile('orders.log', `New order: Ginger Chai at ${new Date()}\n`, 'utf8');
console.log('Order logged!');
// appendFile adds to the END of the file, doesn't overwrite existing content

3. Using writeFile flags for more control:

// Flag: 'w' — Write (default, overwrites)
await fs.writeFile('menu.txt', data, { flag: 'w' });

// Flag: 'a' — Append (same as appendFile)
await fs.writeFile('orders.log', data, { flag: 'a' });

// Flag: 'wx' — Write, but FAIL if file exists (prevents overwriting!)
await fs.writeFile('backup.json', data, { flag: 'wx' });
// Throws error if backup.json already exists — safe for backups!

Real Hyderabad use case — Order logging:

const fs = require('fs/promises');

async function logOrder(customer, item, price) {
  const timestamp = new Date().toISOString();
  const logLine = `[${timestamp}] ${customer} ordered ${item} - Rs. ${price}\n`;
  
  await fs.appendFile('orders.log', logLine, 'utf8');
  console.log(`Order logged for ${customer}`);
}

// Usage:
// await logOrder('Raju', 'Special Chai', 20);
// await logOrder('Priya', 'Samosa', 15);

Every time someone orders, it's appended to orders.log. At end of day, the log file shows all orders — no database needed!

04Directory Operations — Kitchen Management

Directory operations help you manage your kitchen storage — organize files into folders, check what's available, create backups.

1. Reading a directory (see all files in a folder):

const fs = require('fs/promises');

async function listKitchen() {
  const files = await fs.readdir('./kitchen');
  console.log('Kitchen contents:', files);
  // Output: [ 'chai-patti.txt', 'sugar.txt', 'menu.txt', 'orders.log' ]
}

listKitchen();

2. Creating a directory:

await fs.mkdir('./backups');
console.log('Backups folder created!');

// Create nested directories (like mkdir -p)
await fs.mkdir('./data/orders/2024', { recursive: true });
console.log('Nested folders created!');

3. Checking if a file or directory exists:

import { access, constants } from 'fs/promises';

async function checkExists(path) {
  try {
    await access(path, constants.F_OK);
    console.log(`${path} exists!`);
    return true;
  } catch {
    console.log(`${path} does not exist`);
    return false;
  }
}

await checkExists('menu.txt');
await checkExists('biryani.txt');

4. Renaming and deleting:

// Rename file
await fs.rename('old-menu.txt', 'new-menu.txt');

// Delete file
await fs.unlink('old-recipe.txt');

// Delete directory (must be empty)
await fs.rmdir('./empty-folder');

// Delete directory and everything inside (like rm -rf)
await fs.rm('./backups', { recursive: true, force: true });

These operations are essential for file management in any real application — creating upload folders, organizing logs, managing backups, and cleaning up temp files.

05File Stats & Watching — Inventory Check

Sometimes you need to know more about a file than just its content — like its size, when it was created, when it was last modified. And sometimes you want to watch for changes — like a chef watching when new ingredients arrive.

1. File stats (size, dates, permissions):

const fs = require('fs/promises');

async function getFileInfo(path) {
  const stats = await fs.stat(path);
  
  console.log('File info for:', path);
  console.log('Size:', stats.size, 'bytes');
  console.log('Created:', stats.birthtime);
  console.log('Modified:', stats.mtime);
  console.log('Is file:', stats.isFile());
  console.log('Is directory:', stats.isDirectory());
  
  // File size in human-readable format
  if (stats.size < 1024) {
    console.log(`${stats.size} bytes`);
  } else {
    console.log(`${(stats.size / 1024).toFixed(1)} KB`);
  }
}

getFileInfo('menu.txt');

2. Watching a file for changes (real-time):

const fs = require('fs');

// Watch a file — runs callback whenever the file changes
fs.watch('menu.txt', (eventType, filename) => {
  console.log(`Event: ${eventType}`);
  console.log(`File changed: ${filename}`);
  console.log('Menu updated! Reloading...');
  // You could re-read the file here
});

console.log('Watching menu.txt for changes...');
// Now go edit menu.txt in your editor — you'll see the watch trigger!

3. Watch multiple files in a directory:

// Watch an entire directory
fs.watch('./kitchen', { recursive: true }, (event, filename) => {
  console.log(`${filename} changed (${event})`);
  // Useful for auto-reloading servers during development!
});

console.log('Watching kitchen directory...');

File watching is how tools like nodemon work — they watch your files and restart the server when anything changes. It's also used for live reload in development, monitoring config files, and watching log directories.

Stage 1 Complete! ➕ You now know: what Node.js is, npm and package.json, how to create an HTTP server, how modules work, and how to read/write files. Next up: Stage 2 — Express Routes!

Key Takeaways

  • ✅ fs module is built-in — no npm install needed. Has 3 APIs: callbacks, sync, promises.
  • ✅ Always prefer fs.promises (Promise version) for production — non-blocking + async/await.
  • ✅ readFile reads files, writeFile writes/overwrites, appendFile adds to end.
  • ✅ Pass 'utf8' encoding for text files. Without it, you get a Buffer (binary data).
  • ✅ Use { recursive: true } with mkdir for nested directory creation.
  • ✅ fs.watch() lets you monitor files/directories for changes in real-time.
  • ✅ fs.stat() gives detailed file info: size, creation date, modification date, type.
Course Search
Search across all chapters & stages
📖

Search the course

Type any topic — branching, stash, rebase, hooks — and jump straight to that chapter.

merge branchesgit stashundo commitrebase