Node.js File System: Quick Reference for fs Module Common APIs

In Node.js, the File System (fs) module is a core component for handling file reading, writing, directory management, and other operations. The fs module provides a rich set of APIs to directly manipulate disk files in code. This article compiles the most commonly used fs APIs for beginners, with simple examples to help you get started quickly.

一、Basic Concepts: Synchronous vs Asynchronous

The APIs in the fs module are categorized into synchronous and asynchronous styles:
- Synchronous methods (e.g., readFileSync, writeFileSync): Code execution blocks waiting for the operation to complete, similar to “executing step by step”. Suitable for simple scripts or debugging, but may cause program lag (especially when handling large files).
- Asynchronous methods (e.g., readFile, writeFile): Code is non-blocking, and results are handled via callback functions or Promise after the operation completes. Suitable for high-concurrency scenarios and requires handling asynchronous flow (e.g., errors, results).

二、Common API Quick Reference

1. Reading Files: fs.readFile (Asynchronous)

Purpose: Asynchronously reads file content.
Syntax: fs.readFile(path[, options], callback)
- path: File path (relative or absolute).
- options: Optional, specifies encoding (e.g., 'utf8'); default returns Buffer (binary data).
- callback: Callback function with parameters (err, data), where err is error information and data is the file content (string or Buffer).

Example (Reading a text file):

const fs = require('fs');

fs.readFile('./example.txt', 'utf8', (err, data) => {
  if (err) { // Error handling: triggered if file not found or permission denied
    console.error('Read failed:', err);
    return;
  }
  console.log('File content:', data); // Outputs file content on success
});

Synchronous Version: fs.readFileSync(path[, options]) (returns content directly; errors throw exceptions)

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

2. Writing Files: fs.writeFile (Asynchronous)

Purpose: Asynchronously writes content to a file (creates the file if it doesn’t exist; overwrites if it does).
Syntax: fs.writeFile(path, data[, options], callback)
- path: Target file path.
- data: Content to write (string or Buffer).
- options: Encoding configuration, etc.
- callback: Callback function with parameter (err) (no return value indicates success).

Example (Writing text content):

const fs = require('fs');
const content = 'Hello, Node.js!';

fs.writeFile('./output.txt', content, 'utf8', (err) => {
  if (err) {
    console.error('Write failed:', err);
    return;
  }
  console.log('File written successfully!');
});

Synchronous Version: fs.writeFileSync(path, data[, options]) (returns directly; errors throw exceptions)

try {
  fs.writeFileSync('./output.txt', 'Content written synchronously', 'utf8');
  console.log('Synchronous write successful!');
} catch (err) {
  console.error('Synchronous write failed:', err);
}

3. Creating Directories: fs.mkdir (Asynchronous)

Purpose: Creates a directory (folder).
Syntax: fs.mkdir(path[, options], callback)
- path: Directory path.
- options: Optional, recursive: true creates nested directories (e.g., mkdir('a/b/c') requires recursive: true).
- callback: Callback function with parameter (err).

Example (Creating a single-level directory):

const fs = require('fs');

// Creates a single-level directory (errors if parent directory doesn't exist)
fs.mkdir('./new-dir', (err) => {
  if (err) {
    console.error('Creation failed:', err);
    return;
  }
  console.log('Directory created successfully!');
});

Recursive Creation of Multi-level Directories:

// Creates nested directories 'a/b/c'
fs.mkdir('./a/b/c', { recursive: true }, (err) => {
  if (err) console.error(err);
  else console.log('Recursive directory created successfully!');
});
  • Delete File: fs.unlink(path, callback)
    Example:
  fs.unlink('./output.txt', (err) => {
    if (err) console.error('Failed to delete file:', err);
    else console.log('File deleted successfully!');
  });
  • Delete Empty Directory: fs.rmdir(path, callback)
    Example:
  fs.rmdir('./new-dir', (err) => {
    if (err) console.error('Failed to delete directory:', err);
    else console.log('Empty directory deleted successfully!');
  });

Note: To delete non-empty directories, use fs.rm (Node.js 14+), specifying recursive: true:

// Recursively delete a directory (including contents)
fs.rm('./a', { recursive: true }, (err) => {
  if (err) console.error(err);
  else console.log('Non-empty directory deleted successfully!');
});

5. Reading Directories: fs.readdir (Asynchronous)

Purpose: Lists all files and subdirectories in a directory.
Syntax: fs.readdir(path, callback)
- path: Directory path.
- callback: Callback function with parameters (err, files), where files is an array of file/directory names.

Example:

fs.readdir('./', (err, files) => {
  if (err) {
    console.error('Failed to read directory:', err);
    return;
  }
  console.log('Directory contents:', files); // Outputs list of files in current directory
});

6. Getting File Information: fs.stat (Asynchronous)

Purpose: Retrieves metadata of a file/directory (size, modification time, etc.).
Syntax: fs.stat(path, callback)
- path: File/directory path.
- callback: Callback function with parameters (err, stats), where stats is an object containing file information.

Common stats Properties:
- stats.isFile(): Is it a file? (true/false)
- stats.isDirectory(): Is it a directory?
- stats.size: File size in bytes
- stats.mtime: Last modification time

Example:

fs.stat('./example.txt', (err, stats) => {
  if (err) {
    console.error('Failed to get file info:', err);
    return;
  }
  console.log('Is directory:', stats.isDirectory());
  console.log('File size:', stats.size, 'bytes');
  console.log('Last modified:', stats.mtime);
});

7. Checking File Existence: fs.existsSync (Synchronous)

Purpose: Quickly checks if a file/directory exists (only synchronous method; use fs.access or fs.stat for asynchronous checks).
Syntax: fs.existsSync(path)
- path: File/directory path.
- Return value: true (exists) or false (does not exist).

Example:

const path = './example.txt';
if (fs.existsSync(path)) {
  console.log('File exists!');
} else {
  console.log('File does not exist!');
}

三、Advanced Tips and Notes

  1. Path Handling: Avoid direct string concatenation; use the path module for safety:
   const path = require('path');
   const fullPath = path.join(__dirname, 'data', 'file.txt'); // Joins paths safely
  1. Asynchronous Error Handling: Always check for err in callbacks; unhandled errors can crash the program.

  2. Performance Optimization: For large files, use Streams (fs.createReadStream) instead of loading everything into memory to avoid high memory usage.

  3. Permission Issues: Ensure the Node.js process has appropriate permissions (read/write/execute) for files/directories.

四、Summary

The fs module is a core tool for file operations in Node.js. Mastering the above APIs covers most basic needs. From simple “read/write text files” to “recursively creating directories”, flexibly use synchronous/asynchronous methods, and pay attention to error handling and path safety to efficiently complete file system-related development.

For advanced scenarios (e.g., streams, pipes, file locks), further learning is recommended. This article serves as a quick-start “reference manual” for your initial exploration.

Xiaoye