How to Read a File in Node.js: Complete Guide to nodejs read file Methods

Use the built-in fs (File System) module to read files via callback-based fs.readFile(), Promise-based fs.promises.readFile(), or streaming fs.createReadStream() for memory-efficient processing.

Node.js provides robust file reading capabilities through its built-in fs module, implemented in the nodejs/node repository. Whether you're building CLI tools or web servers, understanding how to perform a nodejs read file operation is essential for working with local data. The module exposes both callback and Promise-based APIs defined in lib/fs.js that delegate to native C++ bindings for cross-platform performance.

Three Methods for nodejs read file Operations

The fs module offers three distinct patterns for reading file contents, each optimized for different use cases. According to the nodejs/node source code, all methods ultimately invoke the same native file descriptors in src/node_file.cc, ensuring consistent behavior across POSIX and Windows systems.

Callback-Based Approach with fs.readFile

The traditional callback approach uses fs.readFile, defined in lib/fs.js. This method is suitable for quick scripts or when you want to avoid Promise overhead.

const fs = require('fs');
const path = './example.txt';

fs.readFile(path, 'utf8', (err, data) => {
  if (err) {
    console.error('Error reading file:', err);
    return;
  }
  console.log('File contents:', data);
});

The function signature accepts a file path, optional encoding (specify 'utf8' to receive a string instead of a Buffer), and a callback function handling (err, data).

Promise-Based Approach with fs.promises.readFile

For modern async/await patterns, use the Promise-based API exposed via fs.promises. In ES modules, import directly from fs:

import { promises as fs } from 'fs';
const path = './example.txt';

async function read() {
  try {
    const data = await fs.readFile(path, 'utf8');
    console.log('File contents:', data);
  } catch (err) {
    console.error('Error reading file:', err);
  }
}

read();

This approach integrates cleanly with modern JavaScript and avoids callback nesting. The implementation in lib/fs.js wraps the underlying callback API with native Promise resolution.

Streaming Large Files with fs.createReadStream

For large files or when processing data chunk-by-chunk, use fs.createReadStream to avoid loading entire files into memory. As implemented in nodejs/node, this creates a readable stream that emits data events:

import { createReadStream } from 'fs';
import { pipeline } from 'stream';
import { createWriteStream } from 'fs';

const source = createReadStream('./large-file.txt', { encoding: 'utf8' });
const destination = createWriteStream('./copy.txt');

pipeline(source, destination, (err) => {
  if (err) console.error('Pipeline failed:', err);
  else console.log('File streamed successfully');
});

The pipeline utility handles stream cleanup and error propagation automatically.

Internal Architecture of nodejs read file

Understanding the implementation details helps debug performance issues. The nodejs read file stack consists of three layers:

  • lib/fs.js: High-level JavaScript wrapper exposing both callback and Promise APIs (fs.readFile, fs.promises.readFile)
  • src/node_file.cc: Native C++ implementation that interacts with OS file descriptors
  • test/parallel/test-fs-readfile.js: Comprehensive test suite validating edge cases and cross-platform consistency

When you call fs.readFile(), the JavaScript layer in lib/fs.js validates arguments and forwards calls to the C++ bindings in src/node_file.cc, which execute non-blocking I/O via libuv.

Summary

  • Callback API: Use require('fs').readFile() for legacy compatibility or minimal overhead in CommonJS modules
  • Promise API: Use import { promises as fs } with async/await for cleaner error handling and modern JavaScript patterns
  • Streaming: Use createReadStream() for files larger than available memory or when processing data incrementally
  • Encoding: Always specify 'utf8' when reading text files to receive strings instead of Buffer objects
  • Source Location: The implementation spans lib/fs.js (JavaScript API) and src/node_file.cc (native bindings)

Frequently Asked Questions

What is the difference between fs.readFile and fs.promises.readFile?

fs.readFile uses a traditional callback pattern where you provide a function to handle (err, data), while fs.promises.readFile returns a Promise that resolves with the file contents. According to the nodejs/node source in lib/fs.js, the Promise API is a wrapper around the callback implementation, offering better integration with async/await syntax and centralized error handling through try/catch blocks.

When should I use fs.createReadStream instead of fs.readFile?

Use fs.createReadStream when reading files larger than your available memory or when you need to process data incrementally without loading the entire file into RAM. As implemented in src/node_file.cc, streams use chunked reading via file descriptors, whereas fs.readFile buffers the entire contents before invoking your callback or resolving the Promise.

Where is the fs module implemented in the Node.js source code?

The fs module implementation is split between lib/fs.js (high-level JavaScript APIs including both callback and Promise variants) and src/node_file.cc (low-level C++ bindings that interact with the operating system). Documentation is generated from doc/api/fs.md, and behavior is validated by test/parallel/test-fs-readfile.js.

How do I handle file encoding when using nodejs read file methods?

Always pass the encoding string (typically 'utf8') as the second argument to fs.readFile() or fs.promises.readFile(). Without this parameter, the methods return a raw Buffer object; with it, they return a decoded JavaScript string. The encoding logic is handled in the JavaScript layer of lib/fs.js before returning data to your application.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →