nodejs / help

:sparkles: Need help with Node.js? File an Issue here. :rocket:
1.46k stars 279 forks source link

Emit data event once a line in file is read #1165

Closed prog1dev closed 6 years ago

prog1dev commented 6 years ago

Recently I came upon an article The Basics of Node.js Streams. In Reading From Streams section there is a line:

When you are reading data from a file you may decide you emit data event once a line is read.

As far as I know the only way to read file line-by-line is to use readline interface and its emit 'line' events.

Is there a way to emit 'data' events in readable streams once a line of file is read?

ghost commented 6 years ago

@prog1dev

Something like this?

'use strict';

var fs = require('fs');
var EventEmitter = require('events');

class Line extends EventEmitter{
  constructor(file){
    super();

    this.stream = fs.createReadStream(file);
    this.stream.on('data', this.onData.bind(this));
    this.stream.on('end', this.onEnd.bind(this));

    this.buff = Buffer.alloc(0);

    this.lineBuffs = ['\r\n', '\r', '\n'].map(a => Buffer.from(a));
  }

  onData(data){
    this.buff = Buffer.concat([this.buff, data]);

    do{
      var found = false;

      for(var i = 0; i < this.lineBuffs.length; i++){
        var lineBuff = this.lineBuffs[i];
        var index = this.buff.indexOf(lineBuff);

        if(index !== -1){
          found = true;

          var emitBuff = this.buff.slice(0, index);
          this.buff = this.buff.slice(index + lineBuff.length);
          this.emit('data', emitBuff);

          break;
        }
      }
    }while(found);
  }

  onEnd(){
    this.stream.close();
    this.emit('data', this.buff);
    this.emit('end');
  }
};

And here is how you can use it:

var lineReader = new Line('example.txt');

lineReader.on('data', data => {
  console.log(data.toString());
});

Is this what you're looking for?

gireeshpunathil commented 6 years ago

ping @prog1dev

gireeshpunathil commented 6 years ago

closing due to inactivity, please re-open if it is still outstanding.