2017-08-27 21 views
0

NodeJSで45Mbのテキストファイルを読んでいて、その上の各文字に対して何らかの処理をしています。なぜnodejs書き込みストリームがますますメモリ消費を引き起こすのですか?

私のスクリプトの最初のバージョンは、元のファイルから1つの文字を取ったアキュムレータ変数(結果+ = 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(); 

}); 

しかし、それでもまだ、私はメモリ不足エラーを取得しています:私は、私はこれで問題が解決する可能性が一度にディスク1のチャットに直接データを書き込むことができますので、ライトストリームを使用することにしました。私が wstream.write(c)とコメントすれば、スクリプトは問題なく実行されます。どうして?

+0

はあなたのために、ループがで終わるので、私は推測していますおそらく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() 
}) 
} 
関連する問題