Node.js Readline Module

The readline module lets Node.js read input one line at a time from any readable stream, making it the standard tool for building command-line prompts and processing text files.

What Is the Readline Module?

readline is a core Node.js module for reading data from a Readable stream, such as process.stdin or a file stream, line by line instead of as one continuous chunk of bytes. It is commonly used to build interactive command-line tools that prompt a user for input, and to process large text files without loading the entire file into memory at once.

Creating an Interface

Everything in the readline module starts with readline.createInterface(), which pairs an input stream with an optional output stream and returns an interface object. That interface emits a 'line' event every time a newline is detected in the input.

  • readline.createInterface({ input, output }) - creates the interface bound to a readable input stream.
  • rl.on('line', callback) - fires once for every complete line read from the input.
  • rl.question(prompt, callback) - displays a prompt and passes the next line of input to the callback.
  • rl.close() - ends the interface and stops listening for further input.
  • rl.on('close', callback) - fires when the interface is closed or the input stream ends.

Example 1: Reading lines from standard input

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.on('line', (line) => {
  console.log(`Received: ${line}`);
});

rl.on('close', () => {
  console.log('Input stream closed. Goodbye!');
});

Prompting the User for Input

For interactive command-line tools, rl.question() is more convenient than listening for raw 'line' events, since it displays a prompt string and hands you exactly one line of response through a callback.

Example 2: Asking the user a question

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.question('What is your name? ', (name) => {
  console.log(`Hello, ${name}!`);
  rl.close();
});

Reading Line by Line from a File

readline is not limited to the terminal - it works with any Readable stream, including a stream created from a file with fs.createReadStream(). This lets you process very large files one line at a time instead of reading the entire file into memory.

Example 3: Counting lines in a file

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

const rl = readline.createInterface({
  input: fs.createReadStream('data.txt'),
  crlfDelay: Infinity
});

let lineCount = 0;

rl.on('line', (line) => {
  lineCount++;
  console.log(`Line ${lineCount}: ${line}`);
});

rl.on('close', () => {
  console.log(`Total lines read: ${lineCount}`);
});
EventWhen It Fires
lineEvery time a complete line is read from the input stream
closeWhen the interface is closed or the underlying input stream ends
SIGINTWhen the user presses Ctrl+C while the interface is active
Note: Always set crlfDelay: Infinity when reading from files. It tells readline to treat \r\n as a single line ending rather than potentially splitting it across two separate 'line' events, which matters when processing files created on Windows.
Note: The classic readline API is callback and event based. Since Node 17, an experimental readline/promises variant is also available, offering an async/await-friendly rl.question() that resolves with the answer directly instead of requiring a callback.

Exercise: Node.js Readline Module

What is the primary purpose of the readline module?