What is the most efficient way to read only the first line of a file in Node JS?

There's a built-in module almost for this case - readline. It avoids messing with chunks and so forth. The code would look like the following:

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

async function getFirstLine(pathToFile) {
  const readable = fs.createReadStream(pathToFile);
  const reader = readline.createInterface({ input: readable });
  const line = await new Promise((resolve) => {
    reader.on('line', (line) => {
      reader.close();
      resolve(line);
    });
  });
  readable.close();
  return line;
}

I ended up adopting this solution, which seems the most performant I've seen so far:

var fs = require('fs');
var Q = require('q');

function readFirstLine (path) {
  return Q.promise(function (resolve, reject) {
    var rs = fs.createReadStream(path, {encoding: 'utf8'});
    var acc = '';
    var pos = 0;
    var index;
    rs
      .on('data', function (chunk) {
        index = chunk.indexOf('\n');
        acc += chunk;
        index !== -1 ? rs.close() : pos += chunk.length;
      })
      .on('close', function () {
        resolve(acc.slice(0, pos + index));
      })
      .on('error', function (err) {
        reject(err);
      })
  });
}

I created a npm module for convenience, named "firstline".

Thanks to @dandavis for the suggestion to use String.prototype.slice()!


Please try this:

https://github.com/yinrong/node-line-stream-util#get-head-lines

It unpipe the upstream once got the head lines.


I know this doesn't exactly answer the question but for those who are looking for a READABLE and simple way to do so:

const fs = require('fs').promises;

async function getFirstLine(filePath) {
    const fileContent = await fs.readFile(filePath, 'utf-8');
    return (fileContent.match(/(^.*)/) || [])[1] || '';
} 

NOTE:

  • naturaly, this will only work with text files, which I assumed you used from your description
  • this will work with empty files and will return an empty string
  • this regexp is very performant since it is simple (no OR conditions`or complex matches) and only reads the first line