2017-08-27 102 views
0

我正在讀取NodeJS中的45Mb文本文件,並對其上的每個字符進行一些處理。爲什麼nodejs寫入流會導致內存消耗增加?

我的腳本的第一個版本從原始文件中取出一個字符,將它存儲在一個累加器變量(result + = char)中,然後將結果保存在文本文件中。這是行不通的,因爲文件太大了我在RAM上放了太多的數據,所以我得到一個錯誤:Javascript堆內存不足。我決定用寫流這樣我就可以在時間數據直接寫入到磁盤上一個聊天所以這可以解決該問題:

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),劇本將毫無問題地運行。爲什麼?

+0

你的代碼沒有問題你for循環結束的也許1秒,寫作仍然需要100秒。所以基本上它仍然在記憶中......你需要放慢你的'wstream.write(c);'調用。 –

+0

...我甚至會說第一個字符只在退出readFile回調後才寫入。並且在此之前,所有要寫入的數據都會緩存在內存中。 –

+0

那麼?我的解決方案是**跨平臺**,如你所願? – EMX

回答

1

流,流,流...

油門下的I/O:

流在塊輸入,暫停對於每個大塊流,解析&操縱當前組塊中的每個字符並將其寫入輸出。

然後,您可以恢復輸入流以繼續下一個輸入流,直到完成。


我曾與節流使用createReadStream & 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() 
}) 
} 
相關問題