Mastering the FS module In NodeJS

Kinanee Samson - Jul 19 '23 - - Dev Community

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');
Enter fullscreen mode Exit fullscreen mode

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

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!');
  })
Enter fullscreen mode Exit fullscreen mode

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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)
  }
)
Enter fullscreen mode Exit fullscreen mode

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`);
  })
}

Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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
  }
}
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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)
});
Enter fullscreen mode Exit fullscreen mode

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
  }
}
Enter fullscreen mode Exit fullscreen mode

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 }
)
Enter fullscreen mode Exit fullscreen mode

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!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .