The File System Module

The fs module is one of the first things that separates Node from browser JavaScript — a webpage can't touch your hard drive, but a Node script can read and write files directly.

Reading a file synchronously

Given a text file sitting next to the script:

text greeting.txt
Hello from a file!
JS read-sync.js
const fs = require("fs");

const contents = fs.readFileSync("greeting.txt", "utf8");
console.log(contents);
Output
Hello from a file!

The second argument, "utf8", tells readFileSync to hand back a string. Leave it off and you get a raw Buffer of bytes instead — useful for binary files like images, not for text.

Reading a file asynchronously

readFile (no "Sync") takes a callback instead of blocking, so the rest of the program keeps running while the disk read happens in the background:

JS read-async.js
const fs = require("fs");

console.log("Starting read...");

fs.readFile("greeting.txt", "utf8", (err, contents) => {
  if (err) {
    console.error("Read failed:", err.message);
    return;
  }
  console.log("File contents:", contents);
});

console.log("Read requested, moving on...");
Output
Starting read...
Read requested, moving on...
File contents: Hello from a file!

Notice the order: "moving on" prints before the file contents, even though readFile was called first — the callback only runs once the disk read finishes, and Node doesn't wait around for it.

Writing a file

JS write.js
const fs = require("fs");

fs.writeFileSync("output.txt", "Generated by Node.\n");
console.log("Done writing.");
Output
Done writing.
Note: the synchronous versions (readFileSync, writeFileSync) block the entire process until they finish — fine for a one-off script or reading config at startup, but a real problem inside a running web server, where blocking on disk I/O means every other request has to wait too. Servers should reach for the async or promise-based versions instead.