写入文件 fs 流 NodeJS 时出错

Posted

技术标签:

【中文标题】写入文件 fs 流 NodeJS 时出错【英文标题】:Error writing to file fs stream NodeJS 【发布时间】:2016-12-15 16:02:43 【问题描述】:

目标

使用csv-write-stream 和 fs 流将一个非常大的数组写入文件。

背景

我有一个小型应用程序,可将大量数据(数千个条目)写入 CSV 文件。为了实现这一点,我使用了前面提到的库,它只不过是 fs 流的掩码(方便)。但是,应用程序在运行时崩溃,我不知道为什么。

错误

文件被创建并且流开始写入它,但是在执行过程中我总是遇到同样的错误:

events.js:141
      throw er; // Unhandled 'error' event
      ^

Error: write after end
    at writeAfterEnd (_stream_writable.js:166:12)
    at WriteStream.Writable.write (_stream_writable.js:211:5)
    at ondata (_stream_readable.js:536:20)
    at emitOne (events.js:77:13)
    at emit (events.js:169:7)
    at Readable.read (_stream_readable.js:368:10)
    at flow (_stream_readable.js:751:26)
    at WriteStream.<anonymous> (_stream_readable.js:609:7)
    at emitNone (events.js:67:13)
    at WriteStream.emit (events.js:166:7)

代码

我知道这个错误与这段代码有关:

let writer = csvWriter(
    headers: ['country', 'postalCode']
);
let fsStream = fs.createWriteStream('output.csv');
writer.pipe(fsStream);

//very big array !
currCountryCodes = [country: 'A', postalCode: 0, country: 'B', postalCode: 1 ];

for (let j = 0; j < currCountryCodes.length; j++) 
    writer.write(currCountryCodes[j]);


writer.end(function() 
  fsStream.end(function() 
    console.log('=== CSV written successfully, stopping application ===');
    process.exit();
  );
);

最具体的执行:

fsStream.end(function() 
        console.log('=== CSV written successfully, stopping application ===');
        process.exit();
      );

但我不明白为什么会这样。不知何故,它只发生在我正在编写的数组有数千行时,如果我只有十几行,它运行得很好。

问题

通过阅读错误,我得到的印象是在关闭流后我仍在写入文件,但这不可能发生,因为这些函数仅在所有内容都刷新到文件时运行(对吗?)

我的代码有什么问题?

【问题讨论】:

【参考方案1】:

问题是您(可以理解地)假设当writer.end() 的回调被调用时,不会再向fsStream 写入数据,但事实并非如此(如错误所示)。

writer 是duplex stream,这意味着它既可读又可写。通过调用.end() 方法,您是在告诉它您不会再给它写信了。但是,这并不意味着它仍然不可读。

当您随后结束 fsStream 时,某些缓冲区中仍有未刷新的数据将通过管道传输到 fsStream,从而产生错误。

您可以通过侦听writer 上的end 事件来解决此问题,这是可读的等效信号,表示没有数据可供读取:

writer.end(function() 
  writer.on('end', function() 
    fsStream.end(function() 
      console.log('=== CSV written successfully, stopping application ===');
      process.exit();
    );
  );
);

编辑:我认为当writer.end()被调用时,fsStream也会自动结束(所以fsStream.end()是多余的,它的回调可能不会被调用,因为@987654336 @ 事件已经发出)。

如果您想确保所有数据都已刷新到输出文件,您可以在fsStream 上监听finish 事件:

writer.end(function() 
  fsStream.on('finish', function() 
    console.log('=== CSV written successfully, stopping application ===');
    process.exit();
  );
);

甚至:

fsStream.on('finish', function() 
  console.log('=== CSV written successfully, stopping application ===');
  process.exit();
);

writer.end();

【讨论】:

虽然您的建议不再出现错误,但最终消息'=== CSV written successfully, stopping application ===' 不再出现并且应用程序不再终止:S 也许现在我不需要关注 fsStream 事件? @Flame_Phoenix 查看我的编辑。我认为因为.pipe(),你不需要结束fsStream

以上是关于写入文件 fs 流 NodeJS 时出错的主要内容,如果未能解决你的问题,请参考以下文章

nodeJS文件流和事件

在 Node 中使用“fs”写入文件时出错

nodejs模块——fs模块 WriteFile写入文件

node 文件操作 读取,写入 目录的写入读取 文件流 写入流 管道流 压缩 解压

如何在从 NodeJS 中的多个输入流中读取时写入单个文件

Node.js——fs模块(文件系统),创建删除目录(文件),读取写入文件流