NodeJS File System APIs

The file system module comes with a lot of useful functions to work with the files and the folders. We can include the file system module using require as below:

let fs = require('fs');

Here are some of the sample methods for our common usage. As for all other modules, we can find the complete list at the official API documentation here.

//Directory related  
fs.readdir() - Reads the contents of the directory
fs.mkdir()   - Creates a folder
fs.rmdir()   - Renames a folder
fs.mkdtemp() - Creates a temporary folder
fs.rename() - Renames a file or a folder

//File or Link Related
fs.stats        - Returns a fs.Stats object that contains a lot of information about a file
fs.appendFile() - Append to a file. It creates the file, if it is not found.
fs.readFile()   - Read the content of the file.
fs.writeFile()  - Write to a file. It creates the file, if it is not found.
fs.createReadStream() - Creates a readable file stream. Useful for reading large files. 
fs.createWriteStream()- Creates a writeable file stream.
fs.readlink()   - Read the value of a symbolic link

All file system operations have synchronous, callback, and promise-based forms. The callback and the promise versions have the same name and for the synchronous ones, we have to append ‘Sync’ to above method names.

//Examples of asynchronous vs synchronous file system functions 

fs.readFile() vs fs.readFileSync()

fs.mkdir()    vs fs.mkdirSync()

 

Using the Synchronous & the Asynchronous version

As per the general rules, the synchronous calls will block the execution until the call is over where as the asynchronous ones will let the calling program move forward. Hence, if we are using the callback approach we have to use the outcome of the calls within the callback.

Here is an example of using all the three approach.

const fs = require('fs');

try {
  const stats = fs.statSync('test.txt');

  //Both error and successful outcome are available after the function completes
  console.log("Is File : "+ stats.isFile() + " .And, its size is : "+ stats.size +" Bytes.");
} catch (err) {
  console.error(err)
}
const fs = require('fs');

//Use the outcome within the callback of the function
fs.stat('test.txt', (error, stats)=>{
  if(error) {
    console.error(error)
  }

  console.log("Is File : "+ stats.isFile() + " .And, its size is : "+ stats.size +" Bytes.");

});
const fs = require('fs').promises

  fs.stat('test.txt')
  .then((stats) => {
        console.log("Is File : "+ stats.isFile() + " .And, its size is : "+ stats.size+" Bytes.");
  })
  .catch((error) => {
    console.error(error);
  })
const fs = require('fs').promises

//With asyn/await, the code looks very similar to synchronous code
async function testStats(path) {
   try {
     const stats = await fs.stat(path);

     console.log("Is File : "+ stats.isFile() + " .And, its size is : "+ stats.size+" Bytes.");
   }catch (error) {
     console.error(error)
   }
}

testStats('test.txt');

 

Write, Read and Append a File

Let us take another example for our most basic usage – write, read and append. The code below shows how to use the synchronous and asynchronous versions of the APIs. We can also observe how the use of async\await simplifies the asynchronous program.

const fs = require('fs')


const content = 'Some content!'
const appendContent = 'Some more content!'
try {
  fs.writeFileSync('test.txt', content);

  let data = fs.readFileSync('test.txt', 'utf8')
  console.log("Content after write : \n" + data)

  fs.appendFileSync('test.txt', appendContent);

  data = fs.readFileSync('test.txt', 'utf8')
  console.log("Content after append : \n" + data)
} catch (err) {
  console.error(err)
}
const fs = require('fs').promises;

const content = 'Some content!';
const appendContent = 'Some more content!';

async function testWriteReadAppend(){
  try {
    await fs.writeFile('test.txt', content);

    let data = await fs.readFile('test.txt', 'utf8');
    console.log("Content after write : \n" + data)

    await fs.appendFile('test.txt', appendContent);

    data = await fs.readFile('test.txt', 'utf8');
    console.log("Content after append : \n" + data);
  } catch (err) {
    console.error(err)
  }
}

testWriteReadAppend();
const fs = require('fs')


const content = 'Some content!'
const appendContent = 'Some more content!'

fs.writeFile('test.txt', content, (err)=>{
  if(err){console.error(err);}

  fs.readFile('test.txt', 'utf8',(err,data)=>{
    if(err){console.error(err);}

    console.log("Content after write : \n" + data)
    fs.appendFile('test.txt', appendContent,(err)=>{
      if(err){console.error(err);}

      fs.readFile('test.txt', 'utf8',(err, data)=>{
        console.log("Content after append : \n" + data)
      });
    });
  });
});

 

Here is the console output of running any of the above programs.

F:\nodejs\samples\file>node promise-version-using-async-await.js
Content after write :
Some content!
Content after append :
Some content!Some more content!