Node.js - File System
Welcome, future programmers! Today, we're diving into the exciting world of Node.js and its File System module. As your friendly neighborhood computer teacher, I'm here to guide you through this journey with plenty of examples and explanations. So, buckle up and let's get started!
Synchronous vs Asynchronous
Before we jump into the nitty-gritty of file operations, let's talk about two important concepts: synchronous and asynchronous operations.
Imagine you're at a coffee shop. In a synchronous world, you'd order your coffee, wait for it to be made, and then move on to the next task. In an asynchronous world, you'd order your coffee and then go about your business while the barista prepares it.
In Node.js, we have both synchronous and asynchronous methods for file operations. Let's look at an example:
const fs = require('fs');
// Synchronous read
const data = fs.readFileSync('hello.txt', 'utf8');
console.log(data);
// Asynchronous read
fs.readFile('hello.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
In the synchronous version, our program waits until the file is read before moving on. In the asynchronous version, it continues executing while the file is being read, and then runs a callback function when it's done.
Writing a file
Now, let's learn how to write to a file. It's like leaving a note for your future self!
const fs = require('fs');
// Synchronous write
fs.writeFileSync('note.txt', 'Hello, Future Me!');
// Asynchronous write
fs.writeFile('note.txt', 'Hello, Future Me!', (err) => {
if (err) throw err;
console.log('File saved!');
});
In both cases, we're creating (or overwriting) a file called 'note.txt' with the content "Hello, Future Me!". The asynchronous version includes a callback function that runs after the file is written.
Reading a file
Reading a file is like opening that note you left for yourself. Let's see how it's done:
const fs = require('fs');
// Synchronous read
const data = fs.readFileSync('note.txt', 'utf8');
console.log(data);
// Asynchronous read
fs.readFile('note.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
Both methods will output the contents of 'note.txt'. The 'utf8' parameter specifies the encoding of the file.
Open a file
Sometimes, we want more control over how we interact with a file. That's where the open
method comes in:
const fs = require('fs');
// Asynchronous open
fs.open('myfile.txt', 'r', (err, fd) => {
if (err) throw err;
console.log('File opened successfully!');
// Remember to close the file when you're done
fs.close(fd, (err) => {
if (err) throw err;
});
});
This opens 'myfile.txt' in read mode ('r'). The fd
in the callback is a file descriptor, which we'll use for further operations on the file.
Promises API
For those who prefer working with Promises (don't worry if you don't know what these are yet!), Node.js provides a Promise-based API for file operations:
const fs = require('fs').promises;
async function readMyFile() {
try {
const data = await fs.readFile('myfile.txt', 'utf8');
console.log(data);
} catch (error) {
console.error('Error reading file:', error);
}
}
readMyFile();
This achieves the same result as our earlier asynchronous readFile
example, but using modern JavaScript syntax.
Get File Information
Curious about a file's stats? Node.js has got you covered:
const fs = require('fs');
fs.stat('myfile.txt', (err, stats) => {
if (err) throw err;
console.log(`File size: ${stats.size} bytes`);
console.log(`Is it a directory? ${stats.isDirectory()}`);
console.log(`Is it a file? ${stats.isFile()}`);
});
This gives us information like the file size, whether it's a directory or a file, and more.
Closing a File
Remember to always close your files when you're done with them. It's like putting the cap back on your toothpaste!
const fs = require('fs');
fs.open('myfile.txt', 'r', (err, fd) => {
if (err) throw err;
// Do some operations...
fs.close(fd, (err) => {
if (err) throw err;
console.log('File closed successfully');
});
});
Truncate a File
Sometimes you want to keep a file but remove its contents. That's where truncate comes in:
const fs = require('fs');
fs.truncate('myfile.txt', 0, (err) => {
if (err) throw err;
console.log('File content cleared!');
});
This reduces the file to 0 bytes, effectively clearing its contents.
Delete a File
When you're done with a file completely, you can delete it:
const fs = require('fs');
fs.unlink('myfile.txt', (err) => {
if (err) throw err;
console.log('File deleted successfully');
});
Just be careful with this one - there's no undo button in real life!
Create a Directory
Need a new folder? Here's how you make one:
const fs = require('fs');
fs.mkdir('mynewfolder', (err) => {
if (err) throw err;
console.log('Directory created successfully!');
});
Read a Directory
Want to see what's in a directory? Here's how:
const fs = require('fs');
fs.readdir('.', (err, files) => {
if (err) throw err;
console.log('Directory contents:');
files.forEach(file => {
console.log(file);
});
});
This lists all files and subdirectories in the current directory.
Remove a Directory
And finally, if you want to remove a directory:
const fs = require('fs');
fs.rmdir('mynewfolder', (err) => {
if (err) throw err;
console.log('Directory removed successfully');
});
Note that this only works on empty directories.
Methods Reference
Here's a handy table of the methods we've covered:
Method | Description |
---|---|
readFile | Reads the entire contents of a file |
writeFile | Writes data to a file, replacing the file if it already exists |
open | Opens a file for reading or writing |
close | Closes a file descriptor |
stat | Gets information about a file |
truncate | Truncates a file to a specified length |
unlink | Deletes a file |
mkdir | Creates a new directory |
readdir | Reads the contents of a directory |
rmdir | Removes a directory |
And there you have it! You're now equipped with the basics of file system operations in Node.js. Remember, practice makes perfect, so don't be afraid to experiment with these methods. Happy coding!
Credits: Image by storyset