在nodejs中rl.close()发出后,readline不会停止读取行

时间:2017-05-24 08:54:08

标签: node.js readline

我有以下文件我想逐行阅读并在找到“nameserver 8.8.8.8”后停止阅读。

nameserver 8.8.8.8
nameserver 45.65.85.3
nameserver 40.98.3.3

我正在使用nodejs和readline模块

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

function check_resolv_nameserver(){
  // flag indicates whether namerserver_line was found or not
  var nameserver_flag = false;

  const rl = readline.createInterface({
    input: fs.createReadStream('file_to_read.conf')
  });

  rl.on('line', (line) => {
    console.log(`Line from file: ${line}`);
    if (line === 'nameserver 8.8.8.8'){
      console.log('Found the right file. Reading lines should stop here.');
      nameserver_flag = true;
      rl.close();
    }
  });

  rl.on('close', function(){
    if (nameserver_flag === true){
      console.log('Found nameserver 8.8.8.8');
    }
    else {
      console.log('Could not find nameserver 8.8.8.8');
    }
  });
}

check_resolv_nameserver();

因为我在读完第一个匹配后立即用rl.close()发出一个close事件,我希望我的Code只读取第一行然后再继续读取。但我的输出看起来像这样

Line from file: nameserver 8.8.8.8
Found the right file. Reading lines should stop here.
Found nameserver 8.8.8.8
Line from file: nameserver 45.65.85.3
Line from file: nameserver 40.98.3.3

如何在第一场比赛后让readline停止并让我继续其他内容?

6 个答案:

答案 0 :(得分:1)

您也应关闭该流:

const readline = require('readline');
const fs = require('fs');
const readStream = fs.createReadStream('file_to_read.conf');

// More code here ...

const rl = readline.createInterface({
    input: readStream
  });

// Rest of your code

rl.close();
readStream.destroy();

答案 1 :(得分:1)

对于那些无法使linereader停止的人,请执行此操作(在您的readline回调中):

lineReader.close()
lineReader.removeAllListeners()

答案 2 :(得分:0)

我搜索了很长一段时间我没有机会让这个工作......所以我得到了我想要的东西归功于一个节点模块:line-reader

它很好,因为它可以从文件读取,也可以从缓冲区读取。

这是一个简单的代码示例,您可以在其中读取2行然后停止。

const lineReader = require('line-reader');
const stream = require('stream');

let bufferStream = new stream.PassThrough();
bufferStream.end(yourBuffer);

let lineNumber = 0;
lineReader.eachLine(bufferStream, function(line) {
    lineNumber++;
    if (lineNumber === 1 || lineNumber === 2) {
        // Perform whatever
    } else {

        // returning false breaks the reading
        return false;
    }

}, async function finished (err) {
    if (err) {
        // throw error or whatever
    }

    // Do after reading processing here
});

编辑:我找到了一种干净的方式来完全按计划完成所有事情:

1st创建一个拆分器来读取字符串块

class Splitter extends Transform {
    constructor(options){
        super(options);
        this.splitSize = options.splitSize;
        this.buffer = Buffer.alloc(0);
        this.continueThis = true;
    }
    stopIt() {
        this.continueThis = false;
    }

    _transform(chunk, encoding, cb){

        this.buffer = Buffer.concat([this.buffer, chunk]);

        while ((this.buffer.length > this.splitSize || this.buffer.length === 1) && this.continueThis){
            try {
                let chunk = this.buffer.slice(0, this.splitSize);

                this.push(chunk);
                this.buffer = this.buffer.slice(this.splitSize);
                if (this.buffer[0] === 26){
                    console.log('EOF : ' + this.buffer[0]);
                }
            } catch (err) {
                console.log('ERR OCCURED => ', err);
                break;
            }
        }
        console.log('WHILE FINISHED');
        cb();
    }
}

然后将其传输到您的信息流:

let bufferStream = new stream.PassThrough();
bufferStream.end(hugeBuffer);
let splitter = new Splitter({splitSize : 170}); // In my case I have 170 length lines, so I want to process them line by line
let lineNr = 0;
bufferStream
      .pipe(splitter)
      .on('data', async function(line){

          line = line.toString().trim();

          splitter.pause(); // pause stream so you can perform long time processing with await
          lineNr++;

         if (lineNr === 1){
              // DO stuff with 1st line

         } else {
              splitter.stopIt(); // Break the stream and stop reading so we just read 1st line
         }

         splitter.resume() // resumestream so you can process next chunk
    }).on('error', function(err){
            console.log('Error while reading file.' + err);
            // whatever
     }).on('end', async function(){
           console.log('end event');

           // Stream has ended, do whatever...

    });

此代码可逐行启用完美的读取流。如果整个文件不长,则无需使用Splitter

答案 3 :(得分:0)

readline似乎会缓冲一些行,因此您必须添加自己的支票。

示例:

#! /usr/bin/node

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

const reader = readline.createInterface({
    input: fs.createReadStream('test.js')
})

let wasRead = false

reader.on('line', line => {
    if (wasRead) return undefined
    console.log('hello world')
    wasRead = true
    reader.close()
})

答案 4 :(得分:0)

最适合我的是在暂停履历表上添加,让我在阅读后即可编辑文件。

var lineReader = require('readline').createInterface({
    input: require('fs').createReadStream(require('path').resolve('test.js'))
});
lineReader.on('line', function (line) { console.log(line) }) /*loop all lines*/
.on('pause', function () { 
    /* resume after read lines is finished to close file */
    lineReader.resume(); 
}) 
.on('close', function () { 
    /*action after file read is close*/ 
    console.log('Close ok')
}); 

答案 5 :(得分:0)

您可以声明一个行事件侦听器并在需要时将其删除。

const lineEventListener = (line) => {
  // do sth
  // Close
  rl.close();
  rl.removeListener('line', lineEventListener);
}
rl.on('line', lineEventListener);