- Sync API
- Callback async API
- Promise async API
The
fs module (short for file system) is part of the NodeJS standard library. It allows you to work with files and directories on your computer: you can read files, write files, delete them, rename them, and more.To use it, you first need to import it at the top of your file:
const fs = require("fs")
Sync API
The simplest way to use
fs is with its sync methods.These methods block the program until they finish (so the next line of code doesn’t run until the operation is complete).
Here’s an example of reading a file synchronously:
const fs = require("fs") const data = fs.readFileSync("example.txt", "utf8") console.log(data)
If there’s a file called
example.txt in the same directory as your script, this will print its contents.You can also write to a file synchronously:
const fs = require("fs") fs.writeFileSync("output.txt", "Hello from Node!") console.log("File written!")
This creates (or overwrites) a file called
output.txt with the text.Here are some common operations you can do with this API:
const fs = require("fs") // List files and folders const items = fs.readdirSync(".") console.log("Items in current directory:", items) // Create folder fs.mkdirSync("my_folder") console.log("Folder created") // Delete folder fs.rmdirSync("my_folder") console.log("Folder deleted") // Create & write file fs.writeFileSync("my_file.txt", "Hello world") console.log("File created & written") // Read file const content = fs.readFileSync("my_file.txt", "utf8") console.log("File content:", content) // Delete file fs.unlinkSync("my_file.txt") console.log("File deleted")
The Sync API is simple and good for small scripts, but because it blocks the program until it’s done, it can slow things down if you’re working with big files or a server.
Callback async API
The callback API is non-blocking: it lets NodeJS keep doing other things while the file operation happens.
Instead of returning the result directly, it takes a function (a callback) which gets called when the operation is done.
const fs = require("fs") fs.readFile("example.txt", "utf8", (err, data) => { if (err) { console.error("Error reading file:", err) } else { console.log(data) } })
Here’s what happens:
-
fs.readFilestarts readingexample.txt. -
NodeJS does not wait, it moves on to execute other code you might have written.
-
When the file is done reading, the callback runs:
- If there was an error,
errcontains the error. - Otherwise,
datacontains the contents.
- If there was an error,
Here's how you write to a file:
const fs = require("fs") fs.writeFile("output.txt", "Hello async!", (err) => { if (err) { console.error("Error writing file:", err) } else { console.log("File written!") } })
Same idea: the program doesn’t stop while writing the file.
Some examples of things you can do with this API:
const fs = require("fs") // List files and folders fs.readdir(".", (err, items) => { if (err) return console.error(err) console.log("Items in current directory:", items) }) // Create folder fs.mkdir("my_folder", (err) => { if (err) return console.error(err) console.log("Folder created") }) // Delete folder fs.rmdir("my_folder", (err) => { if (err) return console.error(err) console.log("Folder deleted") }) // Create & write file fs.writeFile("my_file.txt", "Hello world", (err) => { if (err) return console.error(err) console.log("File created & written") }) // Read file fs.readFile("my_file.txt", "utf8", (err, content) => { if (err) return console.error(err) console.log("File content:", content) }) // Delete file fs.unlink("my_file.txt", (err) => { if (err) return console.error(err) console.log("File deleted") })
The callback API is better for servers and big tasks because it doesn’t block the program, but nested callbacks can get messy if you chain many operations. That's why a promise-based async API was added.
Promise async API
The Promise-based API is modern and works great with
.then() and async/await. It’s available as fs.promises.You need to import the
promises property:const fs = require("fs").promises
Using
.then():const fs = require("fs").promises fs.readFile("example.txt", "utf8") .then(data => { console.log(data) }) .catch(err => { console.error("Error reading file:", err) })
Or even better, using
async/await:const fs = require("fs").promises async function readFile(fileName) { try { const data = await fs.readFile(fileName, "utf8") console.log(data) } catch (err) { console.error("Error reading file:", err) } } readFile("example.txt")
Writing to a file:
const fs = require("fs").promises async function writeFile(fileName, content) { try { await fs.writeFile(fileName, content) console.log("File written!") } catch (err) { console.error("Error writing file:", err) } } writeFile("output.txt", "Hello from promises!")
The usual list of examples for the API:
const fs = require("fs").promises // Use an async function to await operations async function main() { // List files and folders const items = await fs.readdir(".") console.log("Items in current directory:", items) // Create folder await fs.mkdir("my_folder") console.log("Folder created") // Delete folder await fs.rmdir("my_folder") console.log("Folder deleted") // Create & write file await fs.writeFile("my_file.txt", "Hello world") console.log("File created & written") // Read file const content = await fs.readFile("my_file.txt", "utf8") console.log("File content:", content) // Delete file await fs.unlink("my_file.txt") console.log("File deleted") } main().catch(err => console.error(err))