Nodejs的readline怎么支持字符串逐行读取

Nodejs的readline怎么支持字符串逐行读取

想要逐行读取一个字符串,看了readline表示有点小疑问啊,因为readline.createInterface(options)传进去的input要求是个流,所以我需要将我的字符串转成文本流,尝试用

var fs = require('fs'),
    readline = require('readline');

var Stream = require('stream')
var stream = new Stream()

stream.pipe = function(dest) {
    dest.write(mailcontent)
}

stream.pipe(process.stdout)

console.log(process.input);

var rd = readline.createInterface({
    input: stream,
    output: process.stdout,
    terminal: false
});

rd.on('line', function(line) {
    console.log(line);
});

会报错,如下:

readline.js:142
  input.resume();
        ^
TypeError: Object #<Stream> has no method 'resume'
    at new Interface (readline.js:142:9)
    at Object.exports.createInterface (readline.js:39:10)
    at Readable.<anonymous> (D:\mynodejs\node-server\mailUtil.js:66:47)
    at Readable.g (events.js:180:16)
    at Readable.EventEmitter.emit (events.js:92:17)
    at _stream_readable.js:920:16
    at process._tickCallback (node.js:415:13)

是不是我哪儿理解错了啊?


7 回复

要实现逐行读取字符串的功能,你可以使用 Node.js 的 readline 模块,但需要注意的是,readline 需要一个可读流(Readable Stream)作为输入。因此,你需要将你的字符串转换为一个可读流。

下面是一个示例代码,展示了如何将字符串转换为可读流,并使用 readline 逐行读取:

const { createReadStream } = require('fs');
const readline = require('readline');

// 示例字符串
const mailcontent = `第一行
第二行
第三行`;

// 创建一个可读流
const stringToStream = (str) => {
    const readable = new require('stream').Readable();
    readable.push(str);
    readable.push(null); // 结束标记
    return readable;
};

const stream = stringToStream(mailcontent);

// 使用 readline 创建接口
const rl = readline.createInterface({
    input: stream,
    output: process.stdout,
    terminal: false
});

// 监听 'line' 事件以逐行读取
rl.on('line', (line) => {
    console.log(`读取到一行: ${line}`);
});

// 当所有行都读取完毕时触发 'close' 事件
rl.on('close', () => {
    console.log('所有行已读取完毕');
});

解释

  1. 创建字符串到流的转换函数

    • stringToStream 函数接收一个字符串并返回一个可读流。
    • 使用 require('stream').Readable() 创建一个可读流对象。
    • 使用 readable.push(str) 将字符串推入流中。
    • 使用 readable.push(null) 结束流。
  2. 使用 readline 创建接口

    • 使用 readline.createInterface 方法创建一个 readline 接口,将上述创建的可读流作为输入。
    • 设置输出为 process.stdout,并设置 terminalfalse,因为我们不需要终端交互。
  3. 监听 line 事件

    • 监听 line 事件,当每一行被读取时,触发回调函数并打印该行内容。
  4. 监听 close 事件

    • 监听 close 事件,当所有行都被读取完毕时触发回调函数。

通过这种方式,你可以轻松地将字符串转换为可读流,并使用 readline 模块逐行读取字符串内容。


看起来应该是由String构造的Stream有些问题。 用fs.createReadStream构造的没有问题。

var readline = require('readline'),
    fs = require('fs');

var rl = readline.createInterface({ input: fs.createReadStream(__filename), output: process.stdout, terminal: false });

rl.on(‘line’, function(line) { console.log(’> ’ + line); // you won’t see the last line here, as // there is no \n any more });

Stream好像是类似于抽象的。

今天我也遇到这个问题. readline不适合String. 文件倒是可以根据\r\n去读的.

Readable

有个问题呀,readline咩有参数offset 可以指定行开始读取么

在Node.js中,readline模块确实需要一个流作为输入。字符串本身不是一个流,因此你需要将字符串转换为可读流(Readable Stream),然后再使用readline来逐行读取。

你可以使用stream模块中的Readable类来创建一个可读流,并将字符串传递给它。以下是一个示例代码,展示了如何实现这一点:

const { createReadStream, Readable } = require('stream');
const readline = require('readline');

// 示例字符串
const mailcontent = `这是一行文本。
这是第二行。
第三行在这里。`;

// 创建一个可读流
class StringStream extends Readable {
    constructor(str) {
        super();
        this.str = str;
        this.index = 0;
    }

    _read() {
        if (this.index < this.str.length) {
            const chunk = this.str.substr(this.index, 1024); // 每次读取1024个字符
            this.index += chunk.length;
            this.push(chunk);
        } else {
            this.push(null); // 流结束
        }
    }
}

const stringStream = new StringStream(mailcontent);

const rl = readline.createInterface({
    input: stringStream,
    output: process.stdout,
    terminal: false
});

rl.on('line', (line) => {
    console.log(`读取到一行: ${line}`);
});

rl.on('close', () => {
    console.log('所有行都已读取完毕');
});

解释:

  1. StringStream 类:我们创建了一个继承自Readable的类StringStream,用于将字符串转换为可读流。_read方法是必需的,它从字符串中逐步读取数据并将其推送到流中。
  2. 创建可读流:实例化StringStream类并将字符串传递给它,以创建一个可读流。
  3. 使用 readline:将该可读流传递给readline.createInterface方法,创建一个readline接口。
  4. 处理行事件:通过监听line事件来逐行读取并打印内容。

这样,你就可以使用readline模块逐行读取字符串了。

回到顶部