Net purposes don’t all the time want to put in writing to the file system, however Node.js offers a complete utility programming interface (API) for doing so. It might be important should you’re outputting debugging logs, transferring information to or from a server, or creating command line instruments.

Studying and writing information from code is just not essentially tough, however your utility shall be extra strong should you do the next:

  1. Guarantee it’s cross-platform

    Home windows, macOS, and Linux deal with information in a different way. For instance, you employ a ahead slash / to separate directories in macOS and Linux, however Home windows makes use of a backslash and bans sure file title characters reminiscent of : and ?.

  2. Double-check all the pieces!

    Customers or different apps may delete a file or change entry permissions. At all times test for such points and handle errors successfully.

Desk of Contents

The Node.js fs Module

The Node.js fs module offers strategies for managing information and directories. For those who’re utilizing different JavaScript runtimes:

All JavaScript runtimes run on a single processing thread. The underlying working system handles operations reminiscent of file studying and writing, so the JavaScript program continues to run in parallel. The OS then alerts the runtime when a file operation is full.

The fs documentation offers a protracted listing of capabilities, however there are three basic sorts with comparable capabilities, which we’ll take a look at subsequent.

1. Callback capabilities

These capabilities take a completion callback function as an argument. The next instance passes an inline perform which outputs the content material of myfile.txt. Assuming no errors, its content material shows after finish of program seems within the console:

import { readFile } from 'node:fs';

readFile('myfile.txt', { encoding: 'utf8' }, (err, content material) => {
  if (!err) {
    console.log(content material);
  }
});

console.log('finish of program');

Be aware: the { encoding: 'utf8' } parameter ensures Node.js returns a string of textual content content material relatively than a Buffer object of binary information.

This turns into difficult when it is advisable to run one after one other and descend into nested callback hell! It’s additionally straightforward to put in writing callback capabilities which look appropriate however trigger reminiscence leaks which can be tough to debug.

Usually, there’s little motive to make use of callbacks immediately. Few of the examples beneath use them.

2. Synchronous capabilities

The “Sync” functions successfully ignore Node’s non-blocking I/O and supply synchronous APIs such as you’d discover in different programming languages. The next instance outputs the content material of myfile.txt earlier than finish of program seems within the console:

import { readFileSync } from 'node:fs';

attempt {
  const content material = readFileSync('myfile.txt', { encoding: 'utf8' });
  console.log(content material);
}
catch {}

console.log('finish of program');

It appears simpler, and I’d by no means say don’t use Sync … however, erm … don’t use Sync! It halts the occasion loop and pauses your utility. Which may be advantageous in a CLI program when loading a small initialization file, however contemplate a Node.js net utility with 100 concurrent customers. If one consumer requests a file which takes one second to load, they wait one second for a response — and so do all the opposite 99 customers!

There’s no motive to make use of synchronous strategies when we have now promise capabilities.

3. Promise capabilities

ES6/2015 launched promises. They’re syntactical sugar on callbacks to supply a sweeter, simpler syntax, particularly when used with async/await. Node.js additionally launched a ‘fs/promises’ API which appears and behaves in an analogous strategy to the synchronous function syntax however stays asynchronous:

import { readFile } from 'node:fs/guarantees';

attempt {
  const content material = await readFile('myfile.txt', { encoding: 'utf8' });
  console.log(content material);
}
catch {}

console.log('finish of program');

Be aware using the 'node:fs/guarantees' module and the await earlier than readFile().

Most examples beneath use the promise-based syntax. Most don’t embody attempt and catch for brevity, however it is best to add these blocks to deal with errors.

ES module syntax

The examples on this tutorial additionally use ES Modules (ESM) import relatively than the CommonJS require. ESM is the usual module syntax supported by Deno, Bun, and browser runtimes.

To make use of ESM in Node.js, both:

  • title your JavaScript information with a .mjs extension
  • use an --import=module swap on the command line — reminiscent of node --import=module index.js, or
  • you probably have a undertaking package deal.json file, add a brand new "sort": "module" setting

You may nonetheless use CommonJS require ought to it is advisable to.

Studying Recordsdata

There are a number of capabilities for studying information, however the easiest is to learn a complete file into reminiscence utilizing readFile, as we noticed within the instance above:

import { readFile } from 'node:fs/guarantees';
const content material = await readFile('myfile.txt', { encoding: 'utf8' });

The second choices object may also be a string. It defines the encoding: set 'utf8' or one other textual content format to learn the file content material right into a string.

Alternatively, you may learn strains one after the other utilizing the readLines() method of the filehandle object:

import { open } from 'node:fs/guarantees';

const file = await open('myfile.txt');

for await (const line of file.readLines()) {
  console.log(line);
}

There are additionally extra superior choices for reading streams or any number of bytes from a file.

Dealing with File and Listing Paths

You’ll usually need to entry information at particular absolute paths or paths relative to the Node utility’s working listing. The node:path module offers cross-platform strategies to resolve paths on all working techniques.

The path.sep property returns the listing separator image — on Home windows or / on Linux or macOS:

import * as path from 'node:path';

console.log( path.sep );

However there are extra helpful properties and capabilities. join([…paths]) joins all path segments and normalizes for the OS:

console.log( path.be part of('/undertaking', 'node/example1', '../example2', 'myfile.txt') );

resolve([…paths]) is comparable however returns the complete absolute path:

console.log( path.resolve('/undertaking', 'node/example1', '../example2', 'myfile.txt') );

normalize(path) resolves all listing .. and . references:

console.log( path.normalize('/undertaking/node/example1/../example2/myfile.txt') );

relative(from, to) calculates the relative path between two absolute or relative paths (primarily based on Node’s working listing):

console.log( path.relative('/undertaking/node/example1', '/undertaking/node/example2') );

format(object) builds a full path from an object of constituent elements:

console.log(
  path.format({
    dir: '/undertaking/node/example2',
    title: 'myfile',
    ext: 'txt'
  })
);

parse(path) does the other and returns an object describing a path:

console.log( path.parse('/undertaking/node/example2/myfile.txt') );

Getting File and Listing Data

You usually must get details about a path. Is it a file? Is it a listing? When was it created? When was it final modified? Are you able to learn it? Are you able to append information to it?

The stat(path) perform returns a Stats object containing details about a file or listing object:

import { stat } from 'node:fs/guarantees';

const information = await stat('myfile.txt');
console.log(information);

It additionally offers helpful strategies, together with:

const isFile = information.isFile(); 
const isDirectory = information.isDirectory(); 

The entry(path) perform exams whether or not a file might be accessed utilizing a particular mode set through a constant. If the accessibility test is profitable, the promise fulfills with no worth. A failure rejects the promise. For instance:

import { entry, constants } from 'node:fs/guarantees';

const information = {
  canRead: false,
  canWrite: false,
  canExec: false
};


attempt {
  await entry('myfile.txt', constants.R_OK);
  information.canRead = true;
}
catch {}


attempt {
  await entry('myfile.txt', constants.W_OK);
  information.canWrite = true;
}
catch {}

console.log(information);

You may check a couple of mode, reminiscent of whether or not a file is each readable and writeable:

await entry('myfile.txt', constants.R_OK | constants.W_OK);

Writing Recordsdata

writeFile() is the best perform to asynchronously write a complete file changing its content material if it already exists:

import { writeFile } from 'node:fs/guarantees';
await writeFile('myfile.txt', 'new file contents');

Move the next arguments:

  1. the file path
  2. the file content material — generally is a String, Buffer, TypedArray, DataView, Iterable, or Stream
  3. an non-obligatory third argument generally is a string representing the encoding (reminiscent of 'utf8') or an object with properties reminiscent of encoding and sign to abort the promise.

The same appendFile() function provides new content material to the tip of the present file, creating that file if it doesn’t exist.

For the adventurous, there’s a file handler write() method which lets you substitute content material inside a file at a particular level and size.

Creating Directories

The mkdir() perform can create full listing buildings by passing an absolute or relative path:

import { mkdir } from 'node:fs/guarantees';

await mkdir('./subdir/temp', { recursive: true });

You may go two arguments:

  1. the listing path, and
  2. an non-obligatory object with a recursive Boolean and mode string or integer

Setting recursive to true creates the entire listing construction. The instance above creates subdir within the present working listing and temp as a subdirectory of that. If recursive had been false (the default) the promise would reject if subdir weren’t already outlined.

The mode is the macOS/Linux consumer, group, and others permission with a default of 0x777. This isn’t supported on Home windows and ignored.

The same .mkdtemp() perform is comparable and creates a novel listing usually for short-term information storage.

Studying Listing Contents

.readdir() reads the content material of a listing. The promise fulfills with an array containing all file and listing names (apart from . and ..). The title is relative to the listing and doesn’t embody the complete path:

import { readdir } from 'node:fs/guarantees';

const information = await readdir('./'); 
for (const file of information) {
  console.log(file);
}


You may go an non-obligatory second parameter object with the next properties:

  • encoding — the default is an array of utf8 strings
  • recursive — set true to recursively fetch all information from all subdirectories. The file title will embody the subdirectory title(s). Older editions of Node.js could not present this feature.
  • withFileType — set true to return an array of fs.Dirent objects which incorporates properties and strategies together with .title, .path, .isFile(), .isDirectory() and extra.

The choice .opendir() perform permits you to asynchronously open a listing for iterative scanning:

import { opendir } from 'node:fs/guarantees';

const dir = await opendir('./');
for await (const entry of dir) {
  console.log(entry.title);
}

Deleting Recordsdata and Directories

The .rm() perform removes a file or listing at a specified path:

import { rm } from 'node:fs/guarantees';

await rm('./oldfile.txt');

You may go an non-obligatory second parameter object with the next properties:

  • drive — set true to not increase an error when the trail doesn’t exist
  • recursive — set true to recursively delete a listing and contents
  • maxRetries — make various retries when one other course of has locked a file
  • retryDelay — the variety of milliseconds between retries

The same .rmdir() perform solely deletes directories (you may’t go a file path). Equally, .unlink() solely deletes information or symbolic hyperlinks (you may’t go a listing path).

Different File System Capabilities

The examples above illustrate the most-used choices for studying, writing, updating, and deleting information and directories. Node.js additionally offers additional, lesser-used choices reminiscent of copying, renaming, changing ownership, changing permissions, changing date properties, creating symbolic links, and watching for file changes.

It might be preferable to make use of the callback-based API when anticipating file adjustments, as a result of it’s much less code, simpler to make use of, and might’t halt different processes:

import { watch } from 'node:fs';


watch('./mydir', { recursive: true }, (occasion, file) => {

  console.log(`occasion: ${ occasion }`);

  if (file) {
    console.log(`file modified: ${ file }`);
  }

});


The occasion parameter obtained by the callback is both 'change' or 'rename'.

Abstract

Node.js offers a versatile and cross-platform API to handle information and directories on any working system the place you should use the runtime. With slightly care, you may write strong and transportable JavaScript code that may work together with any file system.

For extra data, discuss with the Node.js fs and path documentation. Different helpful libraries embody:

  • OS to question working oystem data
  • URL to parse a URL, maybe when mapping to and from file system paths
  • Stream for dealing with giant information
  • Buffer and TypedArray objects to deal with binary information
  • Child processes to spawn a subprocess to deal with long-running or advanced file manipulation capabilities.

It’s also possible to discover higher-level file system modules on npm, however there’s no higher expertise than writing your individual.

FAQs on Accessing the File System in Node.js

What’s the File System module in Node.js?

The File System module, also known as fs, is a core module in Node.js that gives strategies and performance for interacting with the file system, together with studying and writing information.

How can I embody the fs module in a Node.js script?

You may embody the fs module through the use of the require assertion, like this: const fs = require('fs');. This makes all fs strategies accessible in your script.

What’s the distinction between synchronous and asynchronous file operations in Node.js?

Synchronous file operations block the Node.js occasion loop till the operation is accomplished, whereas asynchronous operations don’t block the occasion loop, permitting your utility to stay responsive. Asynchronous operations are usually really helpful for I/O duties.

How do I learn the contents of a file in Node.js utilizing the fs module?

You need to use the fs.readFile() methodology to learn the contents of a file. Present the file path and a callback perform to deal with the information as soon as it’s learn.

What’s the goal of the callback perform when working with the fs module in Node.js?

Callback capabilities in fs operations are used to deal with the results of asynchronous file operations. They’re referred to as when the operation is full, passing any errors and information as arguments.

How can I test if a file exists in Node.js utilizing the fs module?

You need to use the fs.existsSync() methodology to test if a file exists at a specified path. It returns true if the file exists and false if it doesn’t.

What’s the fs.createReadStream() methodology, and when is it helpful?

fs.createReadStream() is used for studying giant information effectively. It creates a readable stream for the desired file, permitting you to learn and course of information in smaller, manageable chunks.

Can I take advantage of the fs module to create and write to a brand new file in Node.js?

Sure, you should use the fs.writeFile() or fs.createWriteStream() strategies to create and write to a brand new file. These strategies mean you can specify the file path, content material, and choices for writing.

How do I deal with errors when working with the fs module in Node.js?

You need to all the time deal with errors by checking the error parameter within the callback perform offered to asynchronous fs strategies or through the use of attempt/catch blocks for synchronous operations.

Is it potential to delete a file utilizing the fs module in Node.js?

Sure, you should use the fs.unlink() methodology to delete a file. Present the file path and a callback perform to deal with the consequence.

Can I take advantage of the fs module to work with directories and folder buildings in Node.js?

Sure, the fs module offers strategies to create, learn, and manipulate directories, together with creating directories, itemizing their contents, and eradicating directories.