2016-06-21 54 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

有沒有辦法做到這一點,而無需遞歸? 我的循環實際上是一個循環內的循環,所以我不能真正處理嵌套循環內的一個遞歸調用中的數據。 –

+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

感謝您的詳細解答,但我需要將初始源代碼加載到內存中以計算來自該數據的各種值。它交叉引用每條記錄以創建我將要輸出的數據源,所以我不能使用這種方法。 –