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.