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

Studying and writing information from code will not be essentially tough, however your software might be extra strong when you do the next:

  1. Guarantee it’s cross-platform

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

  2. Double-check every part!

    Customers or different apps might 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. In the event you’re utilizing different JavaScript runtimes:

All JavaScript runtimes run on a single processing thread. The underlying working system handles operations similar to 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 an extended checklist of features, however there are three common varieties with related features, which we’ll take a look at subsequent.

1. Callback features

These features 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');

Observe: the { encoding: 'utf8' } parameter ensures Node.js returns a string of textual content content material slightly than a Buffer object of binary knowledge.

This turns into sophisticated when it’s worthwhile to run one after one other and descend into nested callback hell! It’s additionally straightforward to jot down callback features which look appropriate however trigger reminiscence leaks which are tough to debug.

Normally, there’s little cause to make use of callbacks in the present day. Few of the examples beneath use them.

2. Synchronous features

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 seems 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 software. Which may be positive in a CLI program when loading a small initialization file, however take into account a Node.js net software 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 cause to make use of synchronous strategies when now we have promise features.

3. Promise features

ES6/2015 launched promises. They’re syntactical sugar on callbacks to offer a sweeter, simpler syntax, particularly when used with async/await. Node.js additionally launched a ‘fs/promises’ API which seems and behaves in an identical option 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');

Observe 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 slightly 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:

  • identify your JavaScript information with a .mjs extension
  • use an --import=module change on the command line — similar to node --import=module index.js, or
  • if in case you have a challenge bundle.json file, add a brand new "kind": "module" setting

You’ll be able to nonetheless use CommonJS require ought to it’s worthwhile to.

Studying Information

There are a number of features for studying information, however the easiest is to learn an entire 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 typically wish to entry information at particular absolute paths or paths relative to the Node software’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 features. join([…paths]) joins all path segments and normalizes for the OS:

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

resolve([…paths]) is analogous however returns the total absolute path:

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

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

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

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

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

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

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

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

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

Getting File and Listing Data

You typically have to 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 knowledge 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 data = await stat('myfile.txt');
console.log(data);

It additionally offers helpful strategies, together with:

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

The entry(path) perform exams whether or not a file might be accessed utilizing a selected 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 data = {
  canRead: false,
  canWrite: false,
  canExec: false
};


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


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

console.log(data);

You’ll be able to check multiple mode, similar to whether or not a file is each readable and writeable:

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

Writing Information

writeFile() is the only perform to asynchronously write an entire file changing its content material if it already exists:

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

Cross the next arguments:

  1. the file path
  2. the file content material — could be a String, Buffer, TypedArray, DataView, Iterable, or Stream
  3. an optionally available third argument could be a string representing the encoding (similar to 'utf8') or an object with properties similar to encoding and sign to abort the promise.

An analogous appendFile() function provides new content material to the top 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 change content material inside a file at a selected 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’ll be able to go two arguments:

  1. the listing path, and
  2. an optionally available 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 have 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 analogous and creates a singular listing usually for momentary knowledge storage.

Studying Listing Contents

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

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

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


You’ll be able to go an optionally available 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 identify will embody the subdirectory identify(s). Older editions of Node.js might not present this selection.
  • withFileType — set true to return an array of fs.Dirent objects which incorporates properties and strategies together with .identify, .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.identify);
}

Deleting Information 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’ll be able to go an optionally available second parameter object with the next properties:

  • pressure — set true to not elevate an error when the trail doesn’t exist
  • recursive — set true to recursively delete a listing and contents
  • maxRetries — make plenty of 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 Features

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 similar to copying, renaming, changing ownership, changing permissions, changing date properties, creating symbolic links, and watching for file changes.

It could be preferable to make use of the callback-based API when looking forward to 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 utilize the runtime. With a bit care, you may write strong and transportable JavaScript code that may work together with any file system.

For extra data, seek advice from 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 knowledge
  • Child processes to spawn a subprocess to deal with long-running or advanced file manipulation features.

You can too 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, sometimes called 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’ll be able to embody the fs module by utilizing 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 software to stay responsive. Asynchronous operations are usually advisable for I/O duties.

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

You should 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 features 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 knowledge as arguments.

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

You should 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 knowledge 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 utilize the fs.writeFile() or fs.createWriteStream() strategies to create and write to a brand new file. These strategies can help you 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?

It’s best to all the time deal with errors by checking the error parameter within the callback perform supplied to asynchronous fs strategies or by utilizing attempt/catch blocks for synchronous operations.

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

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

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.