为什么nodejs写入流会导致内存消耗增加?

时间:2017-08-27 17:19:06

标签: node.js

我正在NodeJS中读取一个45Mb的文本文件,并对其上的每个字符进行一些处理。

我的脚本的第一个版本从原始文件中获取了一个char,将它存储在一个accumulator变量(result + = char)中,然后将结果保存到一个文本文件中。这不起作用,因为文件太大我在RAM上放了太多数据,所以我收到一个错误: Javascript Heap out of memory 。我决定使用写入流,这样我就可以在一次聊天时直接将数据写入磁盘,这样可以解决问题:

fs = require('fs');

var proportion = 2;

var c = '';

fs.readFile('./concat/all.txt', 'utf8', function (err,data) {
    if (err) {
        return console.log(err);
    }

    var h = parseInt(Math.sqrt(data.length / proportion));
    var w = parseInt(h * proportion);

    console.log(w, h);

    var wstream = fs.createWriteStream('output.txt');


    var lineCount = 0;
    for(var x = 0; x < data.length; x++) {

        if(data.charCodeAt(x) === 32 && x > 0 && data.charCodeAt(x - 1) === 32)
            continue;

        if(data.charCodeAt(x) === 10 && x > 0 && data.charCodeAt(x - 1) === 10)
            continue;

        c = (data.charCodeAt(x) === 10 || data.charCodeAt(x) === 13 || data.charCodeAt(x) === 9) ? " " : data.charAt(x);
        lineCount++;
        if(lineCount > w) {
            c += "\n";
            lineCount = 0;
        }


        wstream.write(c);
    }

    wstream.end();

});

但是,我仍然遇到内存不足错误。如果我评论wstream.write(c),脚本运行没有问题。为什么呢?

1 个答案:

答案 0 :(得分:1)

流,流,流......

限制I / O:

以块的形式传输输入,为每个块暂停流,解析&amp;操纵当前块的每个字符并将其写入输出。

然后你可以恢复输入流继续下一个,重复直到完成。

我使用createReadStream&amp; amp;来限制您的代码是没有问题的createWriteStream

以下是代码(使用64MB文件成功测试)

const fs = require('fs')
var w;  var charCount = 0;  var proportion = 2
//:This step was required to populate 'w'
fs.readFile('input.txt', 'utf8', function (err,data) {
 if(err){return console.log(err)}
 let h = parseInt(Math.sqrt(data.length / proportion))
 w = parseInt(h * proportion); data = undefined;
 console.log('[+] starting  ( w:',w,')'); EMX()
});
//:Here is the magick
function EMX(){
 const I = fs.createReadStream('input.txt')
 const O = fs.createWriteStream('output.txt')
 I.on('end',()=>{console.log("[+] operation completed")})
 I.on('data', (chunk) => {
  I.pause(); let data = chunk.toString()
  for(var x=0;x<data.length;x++){
   if(data.charCodeAt(x) === 32 && x > 0 && data.charCodeAt(x - 1) === 32) continue
   if(data.charCodeAt(x) === 10 && x > 0 && data.charCodeAt(x - 1) === 10) continue
   c = (data.charCodeAt(x) === 10 || data.charCodeAt(x) === 13 || data.charCodeAt(x) === 9) ? " " : data.charAt(x)
   if(charCount>w){c+="\n";charCount=0;} charCount++
   O.write(c)
  }
  I.resume()
 })
}