File system (fs module)

Node.js is a powerful platform for building server-side applications using JavaScript. One of its core features is the fs module, which provides an API for interacting with the file system. In this chapter, we'll explore the fs module in depth, covering everything from basic file operations to advanced techniques. By the end of this chapter, you'll have a comprehensive understanding of how to work with the file system in Node.js.

Introduction to the fs Module

The fs module in Node.js allows you to work with the file system on your computer. It provides functions for reading, writing, updating, and deleting files, as well as working with directories. The fs module can be used in both synchronous and asynchronous modes.

To use the fs module, you need to require it in your Node.js script:

				
					const fs = require('fs');

				
			

Reading Files

Synchronous Reading

Synchronous methods block the execution of the code until the operation is completed. While this can be simpler to use, it can also cause performance issues in a production environment.

				
					const fs = require('fs');

try {
  const data = fs.readFileSync('example.txt', 'utf8');
  console.log(data);
} catch (err) {
  console.error(err);
}

				
			

Explanation:

  • fs.readFileSync('example.txt', 'utf8') reads the content of example.txt in UTF-8 encoding.
  • If the file is read successfully, it logs the content to the console.
  • If an error occurs (e.g., file not found), it logs the error.
				
					// Output //
Content of the example.txt file

				
			

Asynchronous Reading

Asynchronous methods allow other operations to continue while the file operation is being performed.

				
					const fs = require('fs');

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

				
			

Explanation:

  • fs.readFile('example.txt', 'utf8', callback) reads the content of example.txt in UTF-8 encoding.
  • The callback function is executed once the read operation is completed.
  • If an error occurs, it logs the error; otherwise, it logs the file content.
				
					// Output //
Content of the example.txt file

				
			

Streaming Files

File streams are useful for reading large files without loading the entire file into memory.

				
					const fs = require('fs');

const readStream = fs.createReadStream('example.txt', 'utf8');

readStream.on('data', (chunk) => {
  console.log(chunk);
});

readStream.on('error', (err) => {
  console.error(err);
});

readStream.on('end', () => {
  console.log('Finished reading the file');
});

				
			

Explanation:

  • fs.createReadStream('example.txt', 'utf8') creates a readable stream for example.txt in UTF-8 encoding.
  • The data event is fired whenever a chunk of data is available to read.
  • The error event is fired if an error occurs.
  • The end event is fired when the entire file has been read.
				
					// Output //
Content of the example.txt file
Finished reading the file

				
			

Writing Files

Synchronous Writing

Synchronous writing methods block the execution until the operation completes.

				
					const fs = require('fs');

try {
  fs.writeFileSync('output.txt', 'Hello, World!', 'utf8');
  console.log('File written successfully');
} catch (err) {
  console.error(err);
}

				
			

Explanation:

  • fs.writeFileSync('output.txt', 'Hello, World!', 'utf8') writes the string ‘Hello, World!’ to output.txt in UTF-8 encoding.
  • If the operation is successful, it logs a success message.
  • If an error occurs, it logs the error.
				
					// Output //
File written successfully

				
			

Asynchronous Writing

Asynchronous writing methods allow other operations to continue while the file operation is being performed.

				
					const fs = require('fs');

fs.writeFile('output.txt', 'Hello, World!', 'utf8', (err) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('File written successfully');
});

				
			

Explanation:

  • fs.writeFile('output.txt', 'Hello, World!', 'utf8', callback) writes the string ‘Hello, World!’ to output.txt in UTF-8 encoding.
  • The callback function is executed once the write operation is completed.
  • If an error occurs, it logs the error; otherwise, it logs a success message.
				
					// Output //
File written successfully

				
			

Streaming to Files

File streams are useful for writing large files without loading the entire file into memory.

				
					const fs = require('fs');

const writeStream = fs.createWriteStream('output.txt', 'utf8');

writeStream.write('Hello, ');
writeStream.write('World!');
writeStream.end();

writeStream.on('finish', () => {
  console.log('Finished writing to the file');
});

writeStream.on('error', (err) => {
  console.error(err);
});

				
			

Explanation:

  • fs.createWriteStream('output.txt', 'utf8') creates a writable stream for output.txt in UTF-8 encoding.
  • writeStream.write('Hello, ') writes ‘Hello, ‘ to the file.
  • writeStream.write('World!') writes ‘World!’ to the file.
  • writeStream.end() ends the stream.
  • The finish event is fired when all data has been flushed to the file.
  • The error event is fired if an error occurs.
				
					// Output //
Finished writing to the file

				
			

Working with Directories

Creating Directories

You can create directories using synchronous or asynchronous methods.

Example (Synchronous):

				
					const fs = require('fs');

try {
  fs.mkdirSync('new-directory');
  console.log('Directory created successfully');
} catch (err) {
  console.error(err);
}

				
			

Example (Asynchronous):

				
					const fs = require('fs');

fs.mkdir('new-directory', (err) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('Directory created successfully');
});

				
			

Removing Directories

You can remove directories using synchronous or asynchronous methods.

Example (Synchronous):

				
					const fs = require('fs');

try {
  fs.rmdirSync('directory-path');
  console.log('Directory removed successfully');
} catch (err) {
  console.error(err);
}

				
			

Example (Asynchronous):

				
					const fs = require('fs');

fs.rmdir('directory-path', (err) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('Directory removed successfully');
});

				
			

File Information

Checking File/Directory Existence

You can check if a file or directory exists using synchronous or asynchronous methods.

Example (Synchronous):

				
					const fs = require('fs');

const exists = fs.existsSync('file-or-directory-path');
console.log(exists ? 'Exists' : 'Does not exist');

				
			

Example (Asynchronous):

				
					const fs = require('fs');

fs.access('file-or-directory-path', fs.constants.F_OK, (err) => {
  console.log(err ? 'Does not exist' : 'Exists');
});

				
			

Getting File/Directory Information

You can get information about a file or directory using synchronous or asynchronous methods.

Example (Synchronous):

				
					const fs = require('fs');

try {
  const stats = fs.statSync('file-or-directory-path');
  console.log(stats);
} catch (err) {
  console.error(err);
}

				
			

Example (Asynchronous):

				
					const fs = require('fs');

fs.stat('file-or-directory-path', (err, stats) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(stats);
});

				
			

File and Directory Operations

Renaming Files/Directories

You can rename files or directories using synchronous or asynchronous methods.

Example (Synchronous):

				
					const fs = require('fs');

try {
  fs.renameSync('old-path', 'new-path');
  console.log('Renamed successfully');
} catch (err) {
  console.error(err);
}

				
			

Example (Asynchronous):

				
					const fs = require('fs');

fs.rename('old-path', 'new-path', (err) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('Renamed successfully');
});

				
			

Deleting Files

You can delete files using synchronous or asynchronous methods.

Example (Synchronous):

				
					const fs = require('fs');

try {
  fs.unlinkSync('file-path');
  console.log('File deleted successfully');
} catch (err) {
  console.error(err);
}

				
			

Example (Asynchronous):

				
					const fs = require('fs');

fs.unlink('file-path', (err) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('File deleted successfully');
});

				
			

Copying Files

You can copy files using synchronous or asynchronous methods.

Example (Synchronous):

				
					const fs = require('fs');

try {
  fs.copyFileSync('source-file', 'destination-file');
  console.log('File copied successfully');
} catch (err) {
  console.error(err);
}

				
			

Example (Asynchronous):

				
					const fs = require('fs');

fs.copyFile('source-file', 'destination-file', (err) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('File copied successfully');
});

				
			

File Permissions

Changing File Permissions

You can change the permissions of a file using synchronous or asynchronous methods.

Example (Synchronous):

				
					const fs = require('fs');

try {
  fs.chmodSync('file-path', 0o755);
  console.log('Permissions changed successfully');
} catch (err) {
  console.error(err);
}

				
			

Example (Asynchronous):

				
					const fs = require('fs');

fs.chmod('file-path', 0o755, (err) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('Permissions changed successfully');
});

				
			

Changing File Ownership

You can change the ownership of a file using synchronous or asynchronous methods.

Example (Synchronous):

				
					const fs = require('fs');

try {
  fs.chownSync('file-path', uid, gid);
  console.log('Ownership changed successfully');
} catch (err) {
  console.error(err);
}

				
			

Example (Asynchronous):

				
					const fs = require('fs');

fs.chown('file-path', uid, gid, (err) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log('Ownership changed successfully');
});

				
			

Advanced Topics

Watching Files and Directories

You can watch for changes in files or directories using the fs.watch method.

				
					const fs = require('fs');

fs.watch('file-or-directory-path', (eventType, filename) => {
  if (filename) {
    console.log(`${filename} file Changed`);
  }
});

				
			

Explanation:

  • fs.watch('file-or-directory-path', callback) watches for changes in the specified file or directory.
  • The callback function is executed whenever a change occurs.
  • eventType indicates the type of change (e.g., ‘rename’ or ‘change’).
  • filename is the name of the file that changed.
				
					// Output //
example.txt file Changed

				
			

Using Promises with the fs Module

You can use promises with the fs module for better handling of asynchronous operations.

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

async function readFile() {
  try {
    const data = await fs.readFile('example.txt', 'utf8');
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

readFile();

				
			

Explanation:

  • fs.promises provides promise-based versions of the fs module methods.
  • The async function readFile reads the content of example.txt in UTF-8 encoding using await fs.readFile.
  • If the file is read successfully, it logs the content to the console.
  • If an error occurs, it logs the error.
				
					// Output //
Content of the example.txt file

				
			

Error Handling in File Operations

Proper error handling is crucial when working with file operations to ensure the application behaves as expected.

				
					const fs = require('fs');

fs.readFile('nonexistent.txt', 'utf8', (err, data) => {
  if (err) {
    if (err.code === 'ENOENT') {
      console.error('File not found');
    } else {
      console.error(err);
    }
    return;
  }
  console.log(data);
});

				
			

Explanation:

  • The fs.readFile method attempts to read nonexistent.txt.
  • If an error occurs, it checks the error code.
  • If the error code is ENOENT (file not found), it logs ‘File not found’; otherwise, it logs the error.
				
					// Output //
File not found

				
			

The fs module in Node.js is a versatile tool for interacting with the file system. It provides a wide range of methods for reading, writing, and manipulating files and directories. By understanding both synchronous and asynchronous operations, as well as advanced topics like file watching and promise-based methods, you can build robust and efficient file system operations in your Node.js applications. This chapter has covered the basics to advanced usage of the fs module, providing you with a solid foundation for working with files in Node.js.Happy coding !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India