The fs module is part of the built in Modules that comes with NodeJS by default, this module allows you to create and manipulate files and folders with the drop of a hat and this module is going to be our focus for today.
In today's article we will turn our attention to the fs module in NodeJS and as such we will consider the following;
- How to create a File
- How to read a file
- How to delete a file
- How to create a directory
- How to read a directory
- How to move a file
- How to delete a directory
Creating a file
First you need to import the fs module.
const fs = require('fs');
Next let's declare a function that will help create the file.
const createFile = async (fileName) => {
try {
const file = fs.createWriteStream(fileName);
return file;
} catch (error) {
console.log(error)
}
}
We create a variable createFile
which is equal to an async function, that accepts a single parameter fileName
which will serve as the name of the file. Inside the function we use a try/catch
block to wrap the process of creating a file. Inside the try
block we call fs.createWriteStream
and pass in the fileName as an argument to it. I store the result in a variable file
and I'm just going to return the file. Inside the catch
block we just console.log
any error NodeJS encounters while trying to create that file for us. Let's consume this function.
createFile(__dirname + '/index.json')
.then(file => {
file.write(JSON.stringify({ title: 'Mr.' }));
console.log('file created successfully!');
})
To consume the function we call createFile
function and pass in __dirname
+ /index.json
as the file name and this will create a file named index.json inside the current directory we are working inside. Next we use the write method on the file to add some JSON to the file. We run this file from the terminal using node index.js
command and we get back the message file created successfully and upon inspecting the current working directory we see that the file has been created for us.
Read File
const readFile = (fileName, callback) => {
try {
const readStream = fs.createReadStream(fileName);
let data = [];
readStream.on('data', (chunk) => {
data += chunk
});
readStream.on('end', () => {
callback(null, data)
})
} catch (error) {
callback(error, null);
}
}
I have created a variable readFile
which is equal to an arrow function, the function expects two parameters. The first is fileName
is the name of the file and the second is callback
a callback function. Inside the readFile
function we add a try/catch
block and in the catch block we call callback
and pass in the error as the first argument to it and null as the second argument to it. Inside the try block I have created a variable readStream
which is equal to calling fs.createReadStream
I pass the fileName
argument to it.
I create a second variable data
which is equal to an empty array. This variable will store the contents of the file we read. I listen for the data event on the readStream
and set the data
variable to be += equal to the chunk of data we get from the readStream
. Then I listen for the end event on the readStream
and call the callback function we provided with null as the first argument and the data object we created earlier as the second argument. Let's consume the readFile function.
readFile(
__dirname + '/index.json',
(error, data) => {
if (error) console.log(error)
if (data) console.log(data)
}
)
To consume the readFile
function we call it and pass in the path to the index.json
file which we created earlier. The second argument we pass to the readFile function is a callback that accepts two argument, the first represents an error object while the second is the data that is read from the file. Inside the function we check if there's an error object and we log it out to the console, otherwise we just logout the data if it exits. Save the file and run it from the console and we get an object with title property.
Delete a file
const deleteFile = (file) => {
fs.unlink(file, (err) => {
if (err) throw err;
console.log(`${file} was deleted`);
})
}
I have created a variable deleteFile
which is equal to an arrow function, this function accepts a single parameter file
which represents the path to the file we want to delete. Inside the function we call fs.unlink
and pass the file to it, the unlink function accepts two parameters, the first is the path to file we want to delete. The second argument we pass to the unlink function is an error handler function which will be called with an error object if NodeJS encounters any error while trying to delete the file, we just throw the error if there's one otherwise we just inform the user that the file has been deleted. Let's consume the function next.
deleteFile(__dirname+'/index.json');
In order to delete the index.json
file we created earlier we call the deleteFile
function and pass in the path to the file. Save and run node index.js
from the terminal and we see that the file has been deleted.
Create a folder
const createDirectory = (name) => {
try {
fs.mkdir(name, (err) => {
if (err)
throw Error(err.message);
});
} catch (error) {
throw error
}
}
Let's create a variable createDirectory
which is equal to an arrow function. This function accepts a single parameter, name
which will serve as the name of the folder we are trying to create. Inside the function we use the try/catch
syntax to wrap the process of creating the folder. Inside the catch
block we throw any error NodeJS encounters while trying to create the folder for us. Inside the try
block we call fs.mkdir
and pass in the name as the first argument to it, the mkdir
function accepts two argument, the first is the name of the folder we want to create while the second is an error handler function that will be called with an error object. Inside the error handler function we just throw any error we encounter while trying to create the folder. Then we notify the user that the folder has been created.
createDirectory('helper');
To create our folder we call the createDirectory
function and pass in helper
as the name of the folder we want to create, save it and run it from the command line and you we see that the directory has been created for us.
Read a directory
To read a directory you need to use the fs.readdir
function, this function accepts two parameters, the first is the path to the directory we want to read and the second is a NodeJS style callback function that accepts an error object and a data object. Let's see how this function works.
const fs = require('fs');
const {promisify} = require('util');
const readdir = promisify(fs.readdir);
const checkFiles = async (directory = __dirname) => {
const files = await readdir(directory);
console.log(files);
return files.length;
}
We import and destructure the promisify function from the util
library. The util
library comes baked in with NodeJS by default. We call the promisify function and pass in fs.readdir
as argument to it, I'm going to store the result in a variable readdir.
Let's create a variable checkFiles
which is equal to an async function, the function accepts a single parameter directory
which is an optional parameter, When we call the checkFiles
function we don't always need to pass an argument to it and if we don't then the function will read the current directory we are working with. Inside the checkFiles
function we create a variable files
which is equal to the result of calling await readdir
and passing in the directory
to it then we return the files in the directory.
checkFiles().then((contents) => {
console.log(contents)
});
I call checkFiles and chain the then
method to it, inside the then
method we just console log the contents of the file, let me save the file and run it from the console, and you see we get an array of the files in the folder.
Move file
To move a file in NodeJS you can use the rename function, and let's see how we can achieve this.
const rename = promisify(fs.rename);
const moveFiles = async (
newDirectory,
files
) => {
try {
files.forEach(async (file) => {
await rename(file, `${newDirectory}/${file}`);
});
console.log('file moved');
} catch (error) {
throw error;
}
}
I have converted the rename function on the fs module to a promise by calling the promisify function and saving the result in a variable rename. Next I'm going to create a variable moveFiles
which is equal to an async
function. The function accepts two parameters, the first is the new folder we want to push the file inside and the second is an array of files we want to move.
Inside this function I use the try/catch
block and inside the catch
block i just throw any error encountered while trying to move the files. Inside the try
block I call the forEach method on the files
array and call the rename function for each file in it. The rename function expects two parameters, the first is the file we want to rename, the second is the new name for the file and in this this instance it is the path to the new folder and the name of the file. Then I'm going to alert the user that the file has been created by sending a message to the console.
const files = [
'my-image.jpg',
'my-image.png'
];
moveFiles(`${__dirname}/helper`, files)
I've created an variable files which is equal to an array of files I'll like to move then I call moveFiles
and pass in the helper
directory we created earlier as the first argument to it then I pass in the array we created earlier as the second argument to it. Let me save this file and run it again from the console and you can observe that we get the message that the files have been moved.
Delete a folder
To delete a folder you can use the fs.rm function, let's see how this function works.
const emptyDir = async (directory, {empty}) => {
try {
fs.rm(directory, { recursive: empty }, (err) => {
if(err) throw Error(err);
});
} catch (error) {
throw error
}
}
I have created a file emptyDir
which is equal to an async function. The function expects two parameters, the first is directory
which is the path to the directory we want to delete and the second is an object with an empty property which is a boolean. Inside the function we use the try/catch
syntax to handle this process. Inside catch block we throw any error encountered while trying to delete that directory while in the try block, I call fs.rm
then I pass in the directory as the first argument to it, next I pass in an object with a property recursive which is a boolean that indicates wether or not NodeJS should empty the directory and it's equal to the empty variable we destructured from the config object while the last argument we pass to this function is an error handler function that will be called if any error is encountered while trying to delete the directory. Then we alert the user that the directory has been deleted by printing a message to the console.
emptyDir(
__dirname + '/helper',
{ empty: true }
)
I'm going to call the emptyDir
function and pass in the path to the helper
folder we created earlier, then I pass in an object with an empty property which is equal to true because I want to delete the folder and all it's content because I moved some file into it. Save the file and run it from the terminal and we get the message that the directory has been deleted!