Read a file one line at a time in node.js?

前端 未结 29 1108
深忆病人
深忆病人 2020-11-22 04:33

I am trying to read a large file one line at a time. I found a question on Quora that dealt with the subject but I\'m missing some connections to make the whole thing fit to

29条回答
  •  长发绾君心
    2020-11-22 05:01

    While you should probably use the readline module as the top answer suggests, readline appears to be oriented toward command line interfaces rather than line reading. It's also a little bit more opaque regarding buffering. (Anyone who needs a streaming line oriented reader probably will want to tweak buffer sizes). The readline module is ~1000 lines while this, with stats and tests, is 34.

    const EventEmitter = require('events').EventEmitter;
    class LineReader extends EventEmitter{
        constructor(f, delim='\n'){
            super();
            this.totalChars = 0;
            this.totalLines = 0;
            this.leftover = '';
    
            f.on('data', (chunk)=>{
                this.totalChars += chunk.length;
                let lines = chunk.split(delim);
                if (lines.length === 1){
                    this.leftover += chunk;
                    return;
                }
                lines[0] = this.leftover + lines[0];
                this.leftover = lines[lines.length-1];
                if (this.leftover) lines.pop();
                this.totalLines += lines.length;
                for (let l of lines) this.onLine(l);
            });
            // f.on('error', ()=>{});
            f.on('end', ()=>{console.log('chars', this.totalChars, 'lines', this.totalLines)});
        }
        onLine(l){
            this.emit('line', l);
        }
    }
    //Command line test
    const f = require('fs').createReadStream(process.argv[2], 'utf8');
    const delim = process.argv[3];
    const lineReader = new LineReader(f, delim);
    lineReader.on('line', (line)=> console.log(line));
    

    Here's an even shorter version, without the stats, at 19 lines:

    class LineReader extends require('events').EventEmitter{
        constructor(f, delim='\n'){
            super();
            this.leftover = '';
            f.on('data', (chunk)=>{
                let lines = chunk.split(delim);
                if (lines.length === 1){
                    this.leftover += chunk;
                    return;
                }
                lines[0] = this.leftover + lines[0];
                this.leftover = lines[lines.length-1];
                if (this.leftover) 
                    lines.pop();
                for (let l of lines)
                    this.emit('line', l);
            });
        }
    }
    

提交回复
热议问题