Raj.
Go to Astro's GitHub repo

Write data to file from terminal in node

Rishab Raj

Published on

Intro

Recently I was reading the open source code of consola an open source command line utlity to create beautiful command line prompts at that time I wondered how can we write inputs from terminal to a file in nodejs and after searching a bit I got the answer and all we need is 3 node builtin packages node:readline, node:fs and node:process.

Theory

So before writing code there are some basic concepts which we need to understand,

  1. First one is that a ReadableStream is something from which we can read data it could be a file stream or a stdin
  2. second one is WritableStream to which we can write data, it could be a stream leading to a file or stdout.

So to better understand it suppose stream as a river and if we want to write fishes(data) to it and this stream is leading to a pond(file/terminal) then we will use WritableStream to pipe our fishes(data) to it. If we want to get fishes(data) from the stream which is into the pond(file/terminal) then we will use ReadableStream to pipe fishes.

Techincal Stuff

so now we are going to make a simple terminal app where we can write something on terminal and it gets written into the output file specified by the user. We will create this small terminal app using 2 functions init and read.

init

init function will let the user specify the output filename and call the read function which will take the input from the user and write it to the output file.

lets start with init function which is an async function because it involves promises and it includes only 3 lines of code.

async function init() {
  let ask = readline.createInterface({ input: stdin, output: stdout});
  let output = await ask.question("enter filename to which you want to write data : ");
  read(output);
}

In first line we are creating an instance of readline which takes one required option input which is used to specify the input stream we are using stdin imported from node:process, we are also passing the output stream to which methods like prompt() will write data and it is stdout in our case also imported from same package.


In second line we are using the readline instance’s question() to ask the question and save the response in the output variable.

Note

Here we can use `await` in second line because we are importing the readline from `node:readline/promises` and not from just `node:readline`.

In the third line we are calling the read function by passing output filename as parameter.


read

now lets create read function which involves only 3 statements and an event handler.

function read(output) {
    let reader = readline.createInterface({ input: stdin });
    output = createWriteStream(output);

    reader.prompt();
    reader.on("line", (data) => {
        output?.write(data + "\n");
        reader.prompt()
    });
}

In first line we are again creating a readline interface using stdin as input stream(remember streams) we can also specify file streams here to read data from.


In second line we are creating a write stream to a file using createWriteStream imported from node:fs by passing the name of output file as named by the user.


In third line we are calling prompt function which will let the user enter the text in terminal which should get written inside the output file.


In event handler we are adding a line event handler which will get trigerred when user enters the text and press the enter key, inside the handler we are taking the data written by the user and writing that into the write stream to write it to the output file and again we are calling the prompt method so that user can enter the next line of text and thats it we are done!


at last we just have to call init function to start the process as soon as we start the script.

await init();