Working with the File System in Node.js: Reading and Writing Files

When building backend applications, handling files is one of the most common tasks. For example:

  • Saving user data to a log file

  • Reading configuration files

  • Writing reports or exports

In Node.js, file handling is powered by the built-in fs module (short for File System).

In this blog, we’ll explore:

  1. Using the fs module

  2. Reading files (synchronous and asynchronous)

  3. Writing files (synchronous and asynchronous)

  4. Using Streams for large files

  5. Understanding sync vs async in simple terms


1. Importing the fs Module

The fs module comes with Node.js, so you don’t need to install it.

const fs = require("fs");

2. Reading Files

Asynchronous Read (Preferred):

fs.readFile("example.txt", "utf8", (err, data) => {
  if (err) {
    console.error("Error reading file:", err);
    return;
  }
  console.log("File content:", data);
});

This does not block the program. Other code can still run while the file is being read.

Synchronous Read:

const content = fs.readFileSync("example.txt", "utf8");
console.log("Sync File Content:", content);

This blocks execution until the file is completely read. Good for small scripts, but not recommended for servers.


3. Writing Files

Asynchronous Write:

fs.writeFile("output.txt", "Hello, Node.js!", (err) => {
  if (err) {
    console.error("Error writing file:", err);
    return;
  }
  console.log("File saved asynchronously!");
});

Synchronous Write:

fs.writeFileSync("outputSync.txt", "Hello from Sync!");
console.log("File saved synchronously!");

4. Using Streams for Large Files

Reading or writing very large files at once can be memory-heavy. Instead, Node.js provides streams that process data in chunks.

Read Stream Example:

const readStream = fs.createReadStream("bigfile.txt", "utf8");

readStream.on("data", (chunk) => {
  console.log("Received chunk:", chunk);
});

readStream.on("end", () => {
  console.log("Finished reading file with stream.");
});

Write Stream Example:

const writeStream = fs.createWriteStream("log.txt");

writeStream.write("First log entry\n");
writeStream.write("Second log entry\n");
writeStream.end("Final log entry\n");

writeStream.on("finish", () => {
  console.log("All data written to log.txt");
});

Streams are efficient for logs, video, audio, or large data files.


5. Synchronous vs Asynchronous Explained Simply

Think of it like cooking:

  • Synchronous (Blocking): You cook one dish at a time. Until you finish, you cannot start the next.

  • Asynchronous (Non-Blocking): You put one dish on the stove, then start chopping veggies for another. Both tasks progress in parallel.

Node.js prefers asynchronous operations to handle multiple users efficiently.


Diagram: File Handling in Node.js

Open File → Read or Write → (Sync = Wait) OR (Async = Callback/Promise) → Output Result


Conclusion

  • Use the fs module for file handling in Node.js.

  • Prefer asynchronous methods (readFile, writeFile) for server apps.

  • Use synchronous methods (readFileSync, writeFileSync) only for small scripts or one-time tasks.

  • For large files, streams are the best choice.

With this knowledge, you can confidently work with files in your Node.js applications.

0
Subscribe to my newsletter

Read articles from prashant chouhan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

prashant chouhan
prashant chouhan