【问题标题】:Node.js Readline not writing to output fileNode.js Readline 未写入输出文件
【发布时间】:2018-11-01 02:49:14
【问题描述】:

背景

我正在尝试逐行读取几个 GB 大小的文件。我想处理每一行,然后将其写入文件。我不想(也不能)把一切都记在心里。

重要的是我读取一行的顺序就是我将它写入文件的顺序。

代码

为了实现这一点,我尝试使用 Node.js Readline interface

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

const readStream = fs.createReadStream( "./logs/report.csv" );
const writeStream = fs.createWriteStream( "./logs/out.csv", { encoding: "utf8"} );

const rl = readline.createInterface({
    input: readStream,
    output: writeStream,
    terminal: false,
    historySize: 0
});

rl.on( "line", function(line) {

    //Do your stuff ...
    const transformedLine = line.toUpperCase();
    console.log(transformedLine);

    //Then write to outstream
    rl.write(transformedLine );
});

问题

如您所见,我正在尝试读取一行,对其进行解析,然后将其写入一个名为 out.csv 的文件中。

问题是输出文件总是空的。没有任何东西被写入其中。

我已经阅读了所有的方法、事件和选项,但显然我遗漏了一些东西。

问题

为什么这段代码没有写入文件?

【问题讨论】:

  • 将“终端”设置为 true 会将行写入文件 writestream。
  • 它会在没有任何转换的情况下编写它并限制在历史记录大小。这两件事我都不想要。

标签: javascript node.js file stream


【解决方案1】:

回答

使用当前代码,我实际上是再次用transformedLineReadline

这不是我想要的。我应该做的是直接写信给writeStream

rl.on( "line", function(line) {
    console.log(line);

    //Do your stuff ...
    const transformedLine = line.toUpperCase();
    console.log(transformedLine);

    //Then write to outstream
    writeStream.write( transformedLine );
});

这将产生一个符合输入顺序的输出文件。

有关流机制和内部缓冲区的更详细讨论,请参阅:

【讨论】:

    【解决方案2】:

    我的问题已经很晚了,但是对于任何阅读此内容的人:

    如果您在每个read 上都使用write,并且您的写入速度比读取速度慢,那么您仍然会膨胀内存。虽然不如将整个文件读入内存。

    您应该使用pipestream.Transform 而不是readline。原因是管道在流程中最慢的参与者阶段处理数据,因此不会导致内存膨胀。

    const stream = require('stream');
    const fs = require('fs');
    
    const readStream = fs.createReadStream("./logs/report.csv");
    const writeStream = fs.createWriteStream("./logs/report.csv");
    
    const transformer = new stream.Transform({
      // buffer is a chunk of stream, enc is type of chunk, done is a callback when transform is done
      transform(buffer, enc, done){
        const lines = buffer.toString().split('\n');
        const transformedChunkAsString = lines.map(workYourMagicAndReturnFormattedLine).join('\n');
        const transformedBuffer = Buffer.from(transformedChunkAsString);
        this.push(transformedBuffer);
        done();
      }
    })
    
    readStream.pipe(transformStream).pipe(writeStream);
    
    

    【讨论】:

    • 这种方法的唯一问题是块可能会在行的中间被拆分,因此正则表达式可能与您要查找的内容不匹配。但是,您可以将最后一行(如果未完成)存储在转换函数外部的变量中,并将其添加到下一个块
    【解决方案3】:

    你可以试试这个

    const fs = require( "fs" ),
    readline = require( "readline" );
    
    const readStream = fs.createReadStream("./logs/report.csv");
    const writeStream = fs.createWriteStream("./logs/report.csv");
    
    readStream.pipe(writeStream);
    

    【讨论】:

    • 这样做会创建我的文件的副本。这不是我想要的。如果我尝试转换数据,它也会异步执行,不会保留任何顺序。
    猜你喜欢
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 2014-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多