3

Followup to a solution to reading a file line by line, as described here: https://stackoverflow.com/a/16013228/570796


var fs       = require('fs'),
    readline = require('readline'),
    instream = fs.createReadStream('/path/to/file');

var rl = readline.createInterface(
{
    input: instream,
    terminal: false
});

rl.on('line', function(line) 
{
    console.log(line);
    // if(instream.isEnd()) ...
});

How do I detect if I reached the end of the file?

I understand that there is an event on the ReadStream on('end', () => {/*...*/}) But I need a solution where I can check it through an if statement.

Community
  • 1
  • 1
superhero
  • 6,281
  • 11
  • 59
  • 91

3 Answers3

5

Here's a solution:

let ended = false;
instream.on('end', () => { ended = true });

rl.on('line', function(line) {
    if (ended) {
        //...

However, there's a reasonable chance you don't actually need this, and your application could be structured differently.

I'm not sure whether the line event can even happen after the end event.


Turns out my suspicions were true, so you need to do it this way around.

let lastLine;
rl.on('line', line => { lastLine = line })

instream.on('end', () => {
   assert.notStrictEqual(lastLine, undefined, 'There were no lines!');
   // ...
});
OrangeDog
  • 36,653
  • 12
  • 122
  • 207
  • yhea, two asynchronous events side by side like this is not a go for me :) – superhero Apr 20 '16 at 16:32
  • All Javascript is executed in a single thread; Node.js provides the event queue. When I say I'm not sure it can even happen, I mean however you implement a check it will always be false, so there's no reason to have it. – OrangeDog Apr 20 '16 at 16:40
  • ...maybe my example is different then the context, then pls enlighten me :) – superhero Apr 20 '16 at 16:57
  • Are you actually trying to ask How do I get the last line of a file? – OrangeDog Apr 20 '16 at 17:18
  • What? no I'm asking how to know that I'm reading the last line. – superhero Apr 21 '16 at 00:03
  • Well I've answered the question you asked. If you think it won't work it's probably because you never asked about what you're actually trying to do. – OrangeDog Apr 21 '16 at 07:19
  • I'm listening to what you saying though, reading up on it as well. Also trying a few things out that makes me understand things better. Just when we talking about an asynchronous language, I figured it worked differently. I get back to you later. – superhero Apr 21 '16 at 08:45
  • can't confirm that it works before I actually tried it out, not sure what order the events are being dispatched. Thanks for having patience :) – superhero Apr 21 '16 at 10:16
  • This doesn't work after all, the `stream.on('end', ...` event is never triggered – superhero May 20 '16 at 16:00
  • Oh. I was going from what you originally reported in the question. Best of luck. – OrangeDog May 20 '16 at 16:01
  • fumbling again, it worked in the sense that the event is triggered, but it's triggered after the `line` event is. so, I can't use it to see if it's the last line in that handler. – superhero May 20 '16 at 16:11
  • I always thought that might be the case, hence suggesting you need to restructure your processing. How to proceed depends on what exactly you're trying to do once you've got to the end. – OrangeDog May 20 '16 at 16:14
  • e.g. put the "if ended" logic in the `end` handler, and use the `line` handler to set a `lastLine` variable. – OrangeDog Mar 05 '19 at 17:16
  • Yhea I came a bit longer sense I wrote this question now :) but thanks for taking the time back then when it was relevant :) – superhero Mar 05 '19 at 17:19
5

You can also use the close event.

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

const readInterface = readline.createInterface({
    input: fs.createReadStream("path/to/file.txt"),
    output: process.stdout,
    terminal: false,
})
rl.on("line", function(line){
    console.log(line);
}).on("close", function() {
    console.log("EOF");
})

The close event will run when the file has no more data left to be read from.

1

Another (elegant), approach could be implementing a Promise.

You could furthermore add a reject("Error while reading File"), linked to input.on('error') while reading. But it's not 100% required for your problem.

var fs = require('fs');
var input = require('fs').createReadStream('./inputFile.txt')

var promise = new Promise(function(resolve, reject) {
  var lineReader = require('readline').createInterface({
    input: input
  });
  input.on('end', () => {
    resolve("I reached the end!");
  });

  lineReader.on('line', (line) => {
    // DO STH. WITH EACH LINE (IF DESIRED)
  });
});

promise.then((resolveResult) => {
  // DO WHATEVER YOU WANT TO DO AFTER
}

For more information about promises, I'd check the following introduction:

heldic
  • 367
  • 1
  • 11