2016-06-21 7 views
3

非常に大量のデータを処理していますが、これをファイルに格納しています。私はデータセットを反復処理し、JSONファイルにすべて保存したいと考えています。NodeJSのファイルへのメモリ不足の書き込み

fsを使用してオブジェクトにすべて格納し、それをダンプする初期の方法は、メモリ不足のため動作しませんでした。

私は現在、fs.createWriteStreamを使用していますが、私はまだそれをすべてメモリに格納していると言うことができます。

誰かがより良いやり方を推薦できない限り、データをオブジェクトによってファイルに書きたいと思っています。私のコードの

パート:

// Top of the file 
    var wstream = fs.createWriteStream('mydata.json'); 
    ... 

    // In a loop 
    let JSONtoWrite = {} 
    JSONtoWrite[entry.word] = wordData 

    wstream.write(JSON.stringify(JSONtoWrite)) 

    ... 
    // Outside my loop (when memory is probably maxed out) 
    wstream.end() 

私はストリーム間違っを使用していると思う、誰かがメモリ不足に実行せずにファイルにすべてのデータを書き込む方法を教えてくださいできますか?私がオンラインで見つけたすべての例は、ストリームの読み込みに関連していますが、私がデータ上で行っている計算のため、読み込み可能なストリームを使用することはできません。私はこのファイルに順番に追加する必要があります。

答えて

0

問題は、データがファイルシステムにフラッシュされるのを待っているのではなく、新しいデータと新しいデータを狭いループで同期してストリームにスローし続けることです。

// Top of the file 
    const wstream = fs.createWriteStream('mydata.json'); 
    // I'm no sure how're you getting the data, let's say you have it all in an object 
    const entry = {}; 
    const words = Object.keys(entry); 

    function writeCB(index) { 
     if (index >= words.length) { 
      wstream.end() 
      return; 
     } 

     const JSONtoWrite = {}; 
     JSONtoWrite[words[index]] = entry[words[index]]; 
     wstream.write(JSON.stringify(JSONtoWrite), writeCB.bind(index + 1)); 
    } 

    wstream.write(JSON.stringify(JSONtoWrite), writeCB.bind(0)); 
+0

再帰なしでこれを行う方法はありますか? 私のループは実際にはループ内のループであるため、ネストされたループ内の1回の再帰呼び出しでデータを実際に処理することはできません。 –

+0

このようなコードを整理するには、 'async'(https://www.npmjs.com/package/async)のようなライブラリを使うことを検討してください – Petr

0

あなたも読めるストリーム内のデータソースをラップする必要があります

はここであなたのために働くべきで擬似コードの一部です。あなたのソースは何か分かりませんが、確かめる必要があります。すべてのデータをメモリにロードするわけではありません。

は、例えば、データセットは、JSONオブジェクトが行末文字で分割され、別のファイルから来ると仮定すると、あなたは次のように読むのストリームを作成することができます。

const Readable = require('stream').Readable; 
class JSONReader extends Readable { 
constructor(options={}){ 
    super(options); 
    this._source=options.source: // the source stream 
    this._buffer=''; 
    source.on('readable', function() { 
    this.read(); 
    }.bind(this));//read whenever the source is ready 
} 
_read(size){ 
    var chunk; 
    var line; 
    var lineIndex; 
    var result; 
    if (this._buffer.length === 0) { 
    chunk = this._source.read(); // read more from source when buffer is empty 
    this._buffer += chunk; 
    } 
    lineIndex = this._buffer.indexOf('\n'); // find end of line 
    if (lineIndex !== -1) { //we have a end of line and therefore a new object 
     line = this._buffer.slice(0, lineIndex); // get the character related to the object 
     if (line) { 
     result = JSON.parse(line); 
     this._buffer = this._buffer.slice(lineIndex + 1); 
     this.push(JSON.stringify(line) // push to the internal read queue 
     } else { 
     this._buffer.slice(1) 
     } 
    } 
}} 

は今、あなたが使用することができます

const source = fs.createReadStream('mySourceFile'); 
const reader = new JSONReader({source}); 
const target = fs.createWriteStream('myTargetFile'); 
reader.pipe(target); 

synchronous vs stream memory menagement

は、あなたがより良いメモリフローを持っています

画像と上記の例は優秀なものから得たものです。nodejs in practice book

+0

詳細な答えをありがとうが、私は計算のためにメモリに初期ソースをロードする必要がありますそのデータからの様々な値。それは、私がこのアプローチを使用することはできませんので、私は出力されるデータソースを作成するためにお互いに各レコードを参照します。 –

関連する問題