Working with the File System in JavaScript on Node.js: A Complete Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Working with the File System is Important in Node.js

In modern web development, it's rare to get by without interacting with the file system. Whether it's uploading user avatars, generating logs, processing CSV reports, or reading configuration files — Node.js provides a powerful built-in fs (File System) module for these tasks.

Unlike browser JavaScript, where file access is strictly limited for security purposes, Node.js gives you full control over the server's file system. In this article, we'll break down key operations with practical examples that will help you confidently work with files and folders.



What you will learn:

  • How to read and write files (synchronously and asynchronously)
  • How to work with Streams for large files
  • How to create, rename, and delete folders
  • How to properly handle errors and paths


1. Basics: Reading and Writing Files

The fs module offers three main approaches to working with files: synchronous, asynchronous (with callbacks), and promise-based. It is recommended to use the asynchronous promise-based approach (fs.promises) — it does not block the Event Loop and is easier to read.



1.1 Reading a File

The simplest way to read an entire file is to use readFile.

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

async function readConfig() { try { const data = await fs.readFile('./config.json', 'utf-8'); const config = JSON.parse(data); console.log('Port:', config.port); } catch (err) { console.error('Read error:', err.message); }}

readConfig();

Important: Specify the encoding ('utf-8'), otherwise a Buffer object will be returned.



1.2 Writing to a File

For writing, use writeFile (overwrites the file) or appendFile (appends to the end).

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

async function saveLog(message) { const logLine = `[${new Date().toISOString()}] ${message}`; try { await fs.appendFile('./app.log', logLine); console.log('Log saved'); } catch (err) { console.error('Write error:', err); }}

saveLog('Server started');


2. Working with Large Files: Streams

Imagine you need to read a 2 GB file. The readFile method will load it entirely into RAM, which can lead to memory leaks. For such cases, there are streams (fs.createReadStream and fs.createWriteStream).

A stream processes data in parts (chunks), without storing the entire file in memory.



Example: Copying a Large File

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

const source = path.join(__dirname, 'bigfile.zip');const destination = path.join(__dirname, 'copy.zip');

const readStream = fs.createReadStream(source);const writeStream = fs.createWriteStream(destination);

readStream.on('data', (chunk) => { console.log(`Read ${chunk.length} bytes`); writeStream.write(chunk);});

readStream.on('end', () => { writeStream.end(); console.log('Copying completed');});

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

Tip: For copying, it's more convenient to use the built-in pipeline method from the stream module — it automatically handles errors and closes streams.



3. Managing Directories

Working with folders is an equally important part. Node.js allows you to create, read, and delete directories.



3.1 Creating and Checking a Folder

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

async function ensureDir(dirPath) { try { await fs.mkdir(dirPath, { recursive: true }

Blogs

Book Recommendations